quiver-cli 0.8.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -45
- package/bin/quiver-cli.mjs +3 -1
- package/dist/cli.js +546 -458
- package/package.json +2 -2
- package/template/.agents/AGENTS.md +4 -3
- package/template/.agents/config.json +7 -0
- package/template/.agents/plugins/opencode/rtk.ts +34 -0
- package/template/.agents/skills/agent-browser/SKILL.md +1 -0
- package/template/.agents/skills/apps/skybridge/SKILL.md +4 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +36 -118
- package/template/.agents/skills/design/impeccable/reference/adapt.md +1 -0
- package/template/.agents/skills/design/impeccable/reference/adapt.native.md +58 -0
- package/template/.agents/skills/design/impeccable/reference/android.md +40 -0
- package/template/.agents/skills/design/impeccable/reference/animate.md +73 -188
- package/template/.agents/skills/design/impeccable/reference/audit.md +12 -9
- package/template/.agents/skills/design/impeccable/reference/audit.native.md +139 -0
- package/template/.agents/skills/design/impeccable/reference/bolder.md +19 -101
- package/template/.agents/skills/design/impeccable/reference/clarify.md +59 -253
- package/template/.agents/skills/design/impeccable/reference/colorize.md +51 -222
- package/template/.agents/skills/design/impeccable/reference/craft-floor.md +42 -0
- package/template/.agents/skills/design/impeccable/reference/craft.md +3 -121
- package/template/.agents/skills/design/impeccable/reference/critique.md +44 -23
- package/template/.agents/skills/design/impeccable/reference/degraded/asset-producer.md +90 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/documenter.md +24 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/finish-reviewer.md +37 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/template/.agents/skills/design/impeccable/reference/delight.md +47 -279
- package/template/.agents/skills/design/impeccable/reference/distill.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/doctor.md +53 -0
- package/template/.agents/skills/design/impeccable/reference/document.md +60 -73
- package/template/.agents/skills/design/impeccable/reference/harden.md +1 -12
- package/template/.agents/skills/design/impeccable/reference/hooks.md +20 -5
- package/template/.agents/skills/design/impeccable/reference/init.md +72 -119
- package/template/.agents/skills/design/impeccable/reference/ios.md +45 -0
- package/template/.agents/skills/design/impeccable/reference/layout.md +54 -131
- package/template/.agents/skills/design/impeccable/reference/live-setup.md +102 -0
- package/template/.agents/skills/design/impeccable/reference/live.md +116 -511
- package/template/.agents/skills/design/impeccable/reference/new-work.md +105 -0
- package/template/.agents/skills/design/impeccable/reference/{product.md → operate.md} +6 -5
- package/template/.agents/skills/design/impeccable/reference/optimize.md +4 -4
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -4
- package/template/.agents/skills/design/impeccable/reference/polish.md +68 -212
- package/template/.agents/skills/design/impeccable/reference/quieter.md +3 -3
- package/template/.agents/skills/design/impeccable/reference/routing.md +18 -0
- package/template/.agents/skills/design/impeccable/reference/shape.md +38 -144
- package/template/.agents/skills/design/impeccable/reference/typeset.md +51 -250
- package/template/.agents/skills/design/impeccable/reference/visualize.md +47 -0
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +1 -1
- package/template/.agents/skills/design/impeccable/scripts/concept-seed.mjs +558 -0
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +119 -10
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +534 -45
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +18 -47
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +174 -26
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +233 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +3348 -203
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +297 -97
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +187 -16
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +41 -11
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +16 -2
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +207 -38
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +3082 -173
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +11 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/template/.agents/skills/design/impeccable/scripts/doctor.mjs +336 -0
- package/template/.agents/skills/design/impeccable/scripts/embed-prompt.mjs +133 -0
- package/template/.agents/skills/design/impeccable/scripts/generate-image.mjs +240 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +98 -18
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +46 -6
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +518 -50
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +25 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/artifact-schema.mjs +93 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/composition-catalog.mjs +200 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/concept-catalog.mjs +357 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +27 -7
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +17 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/provider.mjs +5 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/roll-selection.mjs +362 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-deep.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-notice.mjs +169 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/surface-briefs.mjs +151 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/target-slug.mjs +33 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/template-extensions.mjs +146 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-css.mjs +617 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-verify.mjs +60 -0
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/live/completion.mjs +10 -1
- package/template/.agents/skills/design/impeccable/scripts/live/event-validation.mjs +67 -5
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/astro.mjs +47 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/index.mjs +143 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/journal.mjs +197 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
- package/template/.agents/skills/design/impeccable/scripts/live/generation-preflight.mjs +149 -0
- package/template/.agents/skills/design/impeccable/scripts/live/instructions.mjs +142 -0
- package/template/.agents/skills/design/impeccable/scripts/live/poll-lanes.mjs +14 -0
- package/template/.agents/skills/design/impeccable/scripts/live/roots.mjs +508 -0
- package/template/.agents/skills/design/impeccable/scripts/live/session-store.mjs +324 -50
- package/template/.agents/skills/design/impeccable/scripts/live/source-lock.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/source-search.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-ast.mjs +961 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-component.mjs +588 -72
- package/template/.agents/skills/design/impeccable/scripts/live/sveltekit-adapter.mjs +59 -17
- package/template/.agents/skills/design/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +135 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +210 -68
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1562 -223
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +33 -1
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +175 -255
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +26 -6
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +61 -16
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +39 -10
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +573 -47
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +17 -7
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +124 -91
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +88 -26
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +76 -81
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +18 -11
- package/template/.agents/skills/design/impeccable/scripts/serve-question.mjs +932 -0
- package/template/.agents/skills/design/impeccable/scripts/surface-brief.mjs +74 -0
- package/template/.agents/skills/design/shadcn/SKILL.md +46 -11
- package/template/.agents/skills/design/shadcn/cli.md +49 -16
- package/template/.agents/skills/design/shadcn/customization.md +14 -7
- package/template/.agents/skills/design/shadcn/evals/evals.json +30 -0
- package/template/.agents/skills/design/shadcn/mcp.md +27 -16
- package/template/.agents/skills/design/shadcn/registry.md +277 -0
- package/template/.agents/skills/design/shadcn/rules/chat.md +224 -0
- package/template/.agents/skills/design/shadcn/rules/composition.md +20 -2
- package/template/.agents/skills/design/shadcn/rules/styling.md +23 -0
- package/template/.agents/skills/find-skills/SKILL.md +2 -3
- package/template/.agents/skills/hono/SKILL.md +579 -0
- package/template/.agents/skills/integrations/langfuse/SKILL.md +10 -6
- package/template/.agents/skills/integrations/langfuse/references/ci-cd.md +41 -0
- package/template/.agents/skills/integrations/langfuse/references/cli.md +8 -0
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +15 -27
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +39 -52
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +5 -2
- package/template/.agents/skills/integrations/langfuse/references/prompt-engineering.md +35 -0
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +41 -196
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +3 -0
- package/template/.agents/skills/integrations/langfuse/references/trace-evaluator-upgrade.md +76 -0
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +4 -0
- package/template/.agents/skills/integrations/langfuse/references/v4-project-migration.md +73 -0
- package/template/.agents/skills/supabase/CHANGELOG.md +71 -0
- package/template/.agents/skills/supabase/SKILL.md +145 -0
- package/template/.agents/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.agents/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.agents/skills/supabase-postgres-best-practices/CHANGELOG.md +73 -0
- package/template/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_sections.md +39 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_template.md +34 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
- package/template/.agents/upstreams.json +34 -12
- package/template/.agents/skills/design/impeccable/reference/brand.md +0 -108
- package/template/.agents/skills/design/impeccable/reference/codex.md +0 -105
- package/template/.agents/skills/design/impeccable/reference/interaction-design.md +0 -189
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +0 -175
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hono
|
|
3
|
+
description: Use when building Hono web applications or when the user asks about Hono APIs, routing, middleware, JSX, validation, testing, or streaming. TRIGGER when code imports from 'hono' or 'hono/*', or user mentions Hono. Use `npx hono request` to test endpoints.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hono Skill
|
|
7
|
+
|
|
8
|
+
Build Hono web applications. This skill provides inline API knowledge for AI. Use `npx hono request` to test endpoints. If the `hono-docs` MCP server is configured, prefer its tools for the latest documentation over the inline reference.
|
|
9
|
+
|
|
10
|
+
## Hono CLI Usage
|
|
11
|
+
|
|
12
|
+
### Request Testing
|
|
13
|
+
|
|
14
|
+
Test endpoints without starting an HTTP server. Uses `app.request()` internally.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# GET request
|
|
18
|
+
npx hono request [file] -P /path
|
|
19
|
+
|
|
20
|
+
# POST request with JSON body
|
|
21
|
+
npx hono request [file] -X POST -P /api/users -d '{"name": "test"}'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Note:** Do not pass credentials directly in CLI arguments. Use environment variables for sensitive values. `hono request` does not support Cloudflare Workers bindings (KV, D1, R2, etc.). When bindings are required, use `workers-fetch` instead:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx workers-fetch /path
|
|
28
|
+
npx workers-fetch -X POST -H "Content-Type:application/json" -d '{"name":"test"}' /api/users
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Hono API Reference
|
|
34
|
+
|
|
35
|
+
### App Constructor
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Hono } from 'hono'
|
|
39
|
+
|
|
40
|
+
const app = new Hono()
|
|
41
|
+
|
|
42
|
+
// With TypeScript generics
|
|
43
|
+
type Env = {
|
|
44
|
+
Bindings: { DATABASE: D1Database; KV: KVNamespace }
|
|
45
|
+
Variables: { user: User }
|
|
46
|
+
}
|
|
47
|
+
const app = new Hono<Env>()
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Routing Methods
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
app.get('/path', handler)
|
|
54
|
+
app.post('/path', handler)
|
|
55
|
+
app.put('/path', handler)
|
|
56
|
+
app.delete('/path', handler)
|
|
57
|
+
app.patch('/path', handler)
|
|
58
|
+
app.options('/path', handler)
|
|
59
|
+
app.all('/path', handler) // all HTTP methods
|
|
60
|
+
app.on('PURGE', '/path', handler) // custom method
|
|
61
|
+
app.on(['PUT', 'DELETE'], '/path', handler) // multiple methods
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Routing Patterns
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// Path parameters
|
|
68
|
+
app.get('/user/:name', (c) => {
|
|
69
|
+
const name = c.req.param('name')
|
|
70
|
+
return c.json({ name })
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Multiple params
|
|
74
|
+
app.get('/posts/:id/comments/:commentId', (c) => {
|
|
75
|
+
const { id, commentId } = c.req.param()
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// Optional parameters
|
|
79
|
+
app.get('/api/animal/:type?', (c) => c.text('Animal!'))
|
|
80
|
+
|
|
81
|
+
// Wildcards
|
|
82
|
+
app.get('/wild/*/card', (c) => c.text('Wildcard'))
|
|
83
|
+
|
|
84
|
+
// Regexp constraints
|
|
85
|
+
app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
|
|
86
|
+
const { date, title } = c.req.param()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Chained routes
|
|
90
|
+
app
|
|
91
|
+
.get('/endpoint', (c) => c.text('GET'))
|
|
92
|
+
.post((c) => c.text('POST'))
|
|
93
|
+
.delete((c) => c.text('DELETE'))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Route Grouping
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
// Using route()
|
|
100
|
+
const api = new Hono()
|
|
101
|
+
api.get('/users', (c) => c.json([]))
|
|
102
|
+
|
|
103
|
+
const app = new Hono()
|
|
104
|
+
app.route('/api', api) // mounts at /api/users
|
|
105
|
+
|
|
106
|
+
// Using basePath()
|
|
107
|
+
const app = new Hono().basePath('/api')
|
|
108
|
+
app.get('/users', (c) => c.json([])) // GET /api/users
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Error Handling
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
app.notFound((c) => c.json({ message: 'Not Found' }, 404))
|
|
115
|
+
|
|
116
|
+
app.onError((err, c) => {
|
|
117
|
+
console.error(err)
|
|
118
|
+
return c.json({ message: 'Internal Server Error' }, 500)
|
|
119
|
+
})
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Context (c)
|
|
125
|
+
|
|
126
|
+
### Response Methods
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
c.text('Hello') // text/plain
|
|
130
|
+
c.json({ message: 'Hello' }) // application/json
|
|
131
|
+
c.html('<h1>Hello</h1>') // text/html
|
|
132
|
+
c.redirect('/new-path') // 302 redirect
|
|
133
|
+
c.redirect('/new-path', 301) // 301 redirect
|
|
134
|
+
c.body('raw body', 200, headers) // raw response
|
|
135
|
+
c.notFound() // 404 response
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Headers & Status
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
c.status(201)
|
|
142
|
+
c.header('X-Custom', 'value')
|
|
143
|
+
c.header('Cache-Control', 'no-store')
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Variables (request-scoped data)
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
// In middleware
|
|
150
|
+
c.set('user', { id: 1, name: 'Alice' })
|
|
151
|
+
|
|
152
|
+
// In handler
|
|
153
|
+
const user = c.get('user')
|
|
154
|
+
// or
|
|
155
|
+
const user = c.var.user
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Environment (Cloudflare Workers)
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
const value = await c.env.KV.get('key')
|
|
162
|
+
const db = c.env.DATABASE
|
|
163
|
+
c.executionCtx.waitUntil(promise)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Renderer
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
app.use(async (c, next) => {
|
|
170
|
+
c.setRenderer((content) =>
|
|
171
|
+
c.html(
|
|
172
|
+
<html><body>{content}</body></html>
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
await next()
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
app.get('/', (c) => c.render(<h1>Hello</h1>))
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## HonoRequest (c.req)
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
c.req.param('id') // path parameter
|
|
187
|
+
c.req.param() // all path params as object
|
|
188
|
+
c.req.query('page') // query string parameter
|
|
189
|
+
c.req.query() // all query params as object
|
|
190
|
+
c.req.queries('tags') // multiple values: ?tags=A&tags=B → ['A', 'B']
|
|
191
|
+
c.req.header('Authorization') // request header
|
|
192
|
+
c.req.header() // all headers (keys are lowercase)
|
|
193
|
+
|
|
194
|
+
// Body parsing
|
|
195
|
+
await c.req.json() // parse JSON body
|
|
196
|
+
await c.req.text() // parse text body
|
|
197
|
+
await c.req.formData() // parse as FormData
|
|
198
|
+
await c.req.parseBody() // parse multipart/form-data or urlencoded
|
|
199
|
+
await c.req.arrayBuffer() // parse as ArrayBuffer
|
|
200
|
+
await c.req.blob() // parse as Blob
|
|
201
|
+
|
|
202
|
+
// Validated data (used with validator middleware)
|
|
203
|
+
c.req.valid('json')
|
|
204
|
+
c.req.valid('query')
|
|
205
|
+
c.req.valid('form')
|
|
206
|
+
c.req.valid('param')
|
|
207
|
+
|
|
208
|
+
// Properties
|
|
209
|
+
c.req.url // full URL string
|
|
210
|
+
c.req.path // pathname
|
|
211
|
+
c.req.method // HTTP method
|
|
212
|
+
c.req.raw // underlying Request object
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Middleware
|
|
218
|
+
|
|
219
|
+
### Using Built-in Middleware
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { cors } from 'hono/cors'
|
|
223
|
+
import { logger } from 'hono/logger'
|
|
224
|
+
import { basicAuth } from 'hono/basic-auth'
|
|
225
|
+
import { prettyJSON } from 'hono/pretty-json'
|
|
226
|
+
import { secureHeaders } from 'hono/secure-headers'
|
|
227
|
+
import { etag } from 'hono/etag'
|
|
228
|
+
import { compress } from 'hono/compress'
|
|
229
|
+
import { poweredBy } from 'hono/powered-by'
|
|
230
|
+
import { timing } from 'hono/timing'
|
|
231
|
+
import { cache } from 'hono/cache'
|
|
232
|
+
import { bearerAuth } from 'hono/bearer-auth'
|
|
233
|
+
import { jwt } from 'hono/jwt'
|
|
234
|
+
import { csrf } from 'hono/csrf'
|
|
235
|
+
import { ipRestriction } from 'hono/ip-restriction'
|
|
236
|
+
import { bodyLimit } from 'hono/body-limit'
|
|
237
|
+
import { requestId } from 'hono/request-id'
|
|
238
|
+
import { methodOverride } from 'hono/method-override'
|
|
239
|
+
import { trailingSlash, trimTrailingSlash } from 'hono/trailing-slash'
|
|
240
|
+
|
|
241
|
+
// Registration
|
|
242
|
+
app.use(logger()) // all routes
|
|
243
|
+
app.use('/api/*', cors()) // specific path
|
|
244
|
+
app.post('/api/*', basicAuth({ username: 'admin', password: 'secret' }))
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Custom Middleware
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
// Inline
|
|
251
|
+
app.use(async (c, next) => {
|
|
252
|
+
const start = Date.now()
|
|
253
|
+
await next()
|
|
254
|
+
const elapsed = Date.now() - start
|
|
255
|
+
c.res.headers.set('X-Response-Time', `${elapsed}ms`)
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
// Reusable with createMiddleware
|
|
259
|
+
import { createMiddleware } from 'hono/factory'
|
|
260
|
+
|
|
261
|
+
const auth = createMiddleware(async (c, next) => {
|
|
262
|
+
const token = c.req.header('Authorization')
|
|
263
|
+
if (!token) return c.json({ error: 'Unauthorized' }, 401)
|
|
264
|
+
await next()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
app.use('/api/*', auth)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Middleware Execution Order
|
|
271
|
+
|
|
272
|
+
Middleware executes in registration order. `await next()` calls the next middleware/handler, and code after `next()` runs on the way back:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
Request → mw1 before → mw2 before → handler → mw2 after → mw1 after → Response
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
app.use(async (c, next) => {
|
|
280
|
+
// before handler
|
|
281
|
+
await next()
|
|
282
|
+
// after handler
|
|
283
|
+
})
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Validation
|
|
289
|
+
|
|
290
|
+
Validation targets: `json`, `form`, `query`, `header`, `param`, `cookie`.
|
|
291
|
+
|
|
292
|
+
### Zod Validator
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
import { zValidator } from '@hono/zod-validator'
|
|
296
|
+
import { z } from 'zod'
|
|
297
|
+
|
|
298
|
+
const schema = z.object({
|
|
299
|
+
title: z.string().min(1),
|
|
300
|
+
body: z.string()
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
app.post('/posts', zValidator('json', schema), (c) => {
|
|
304
|
+
const data = c.req.valid('json') // fully typed
|
|
305
|
+
return c.json(data, 201)
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Valibot / Standard Schema Validator
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
import { sValidator } from '@hono/standard-validator'
|
|
313
|
+
import * as v from 'valibot'
|
|
314
|
+
|
|
315
|
+
const schema = v.object({ name: v.string(), age: v.number() })
|
|
316
|
+
|
|
317
|
+
app.post('/users', sValidator('json', schema), (c) => {
|
|
318
|
+
const data = c.req.valid('json')
|
|
319
|
+
return c.json(data, 201)
|
|
320
|
+
})
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## JSX
|
|
326
|
+
|
|
327
|
+
### Setup
|
|
328
|
+
|
|
329
|
+
In `tsconfig.json`:
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"compilerOptions": {
|
|
334
|
+
"jsx": "react-jsx",
|
|
335
|
+
"jsxImportSource": "hono/jsx"
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Or use pragma: `/** @jsxImportSource hono/jsx */`
|
|
341
|
+
|
|
342
|
+
**Important:** Files using JSX must have a `.tsx` extension. Rename `.ts` to `.tsx` or the compiler will fail.
|
|
343
|
+
|
|
344
|
+
### Components
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
import type { PropsWithChildren } from 'hono/jsx'
|
|
348
|
+
|
|
349
|
+
const Layout = (props: PropsWithChildren) => (
|
|
350
|
+
<html>
|
|
351
|
+
<head>
|
|
352
|
+
<title>My App</title>
|
|
353
|
+
</head>
|
|
354
|
+
<body>{props.children}</body>
|
|
355
|
+
</html>
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
const UserCard = ({ name }: { name: string }) => (
|
|
359
|
+
<div class="card">
|
|
360
|
+
<h2>{name}</h2>
|
|
361
|
+
</div>
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
app.get('/', (c) => {
|
|
365
|
+
return c.html(
|
|
366
|
+
<Layout>
|
|
367
|
+
<UserCard name="Alice" />
|
|
368
|
+
</Layout>
|
|
369
|
+
)
|
|
370
|
+
})
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### jsxRenderer Middleware
|
|
374
|
+
|
|
375
|
+
Use `jsxRenderer` middleware for layouts. See `npx hono docs /docs/middleware/builtin/jsx-renderer` for details.
|
|
376
|
+
|
|
377
|
+
### Async Components
|
|
378
|
+
|
|
379
|
+
```tsx
|
|
380
|
+
const UserList = async () => {
|
|
381
|
+
const users = await fetchUsers()
|
|
382
|
+
return (
|
|
383
|
+
<ul>
|
|
384
|
+
{users.map((u) => (
|
|
385
|
+
<li>{u.name}</li>
|
|
386
|
+
))}
|
|
387
|
+
</ul>
|
|
388
|
+
)
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Fragments
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
const Items = () => (
|
|
396
|
+
<>
|
|
397
|
+
<li>Item 1</li>
|
|
398
|
+
<li>Item 2</li>
|
|
399
|
+
</>
|
|
400
|
+
)
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Streaming
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
import { stream, streamText, streamSSE } from 'hono/streaming'
|
|
409
|
+
|
|
410
|
+
// Basic stream
|
|
411
|
+
app.get('/stream', (c) => {
|
|
412
|
+
return stream(c, async (stream) => {
|
|
413
|
+
stream.onAbort(() => console.log('Aborted'))
|
|
414
|
+
await stream.write(new Uint8Array([0x48, 0x65]))
|
|
415
|
+
await stream.pipe(readableStream)
|
|
416
|
+
})
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
// Text stream
|
|
420
|
+
app.get('/stream-text', (c) => {
|
|
421
|
+
return streamText(c, async (stream) => {
|
|
422
|
+
await stream.writeln('Hello')
|
|
423
|
+
await stream.sleep(1000)
|
|
424
|
+
await stream.write('World')
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
// Server-Sent Events
|
|
429
|
+
app.get('/sse', (c) => {
|
|
430
|
+
return streamSSE(c, async (stream) => {
|
|
431
|
+
let id = 0
|
|
432
|
+
while (true) {
|
|
433
|
+
await stream.writeSSE({
|
|
434
|
+
data: JSON.stringify({ time: new Date().toISOString() }),
|
|
435
|
+
event: 'time-update',
|
|
436
|
+
id: String(id++)
|
|
437
|
+
})
|
|
438
|
+
await stream.sleep(1000)
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Testing with app.request()
|
|
447
|
+
|
|
448
|
+
Test endpoints without starting an HTTP server:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
// GET
|
|
452
|
+
const res = await app.request('/posts')
|
|
453
|
+
expect(res.status).toBe(200)
|
|
454
|
+
expect(await res.json()).toEqual({ posts: [] })
|
|
455
|
+
|
|
456
|
+
// POST with JSON
|
|
457
|
+
const res = await app.request('/posts', {
|
|
458
|
+
method: 'POST',
|
|
459
|
+
body: JSON.stringify({ title: 'Hello' }),
|
|
460
|
+
headers: { 'Content-Type': 'application/json' }
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
// POST with FormData
|
|
464
|
+
const formData = new FormData()
|
|
465
|
+
formData.append('name', 'Alice')
|
|
466
|
+
const res = await app.request('/users', { method: 'POST', body: formData })
|
|
467
|
+
|
|
468
|
+
// With mock env (Cloudflare Workers bindings)
|
|
469
|
+
const res = await app.request('/api/data', {}, { KV: mockKV, DATABASE: mockDB })
|
|
470
|
+
|
|
471
|
+
// Using Request object
|
|
472
|
+
const req = new Request('http://localhost/api', { method: 'DELETE' })
|
|
473
|
+
const res = await app.request(req)
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## Hono Client (RPC)
|
|
479
|
+
|
|
480
|
+
Type-safe API client using shared types between server and client.
|
|
481
|
+
|
|
482
|
+
**IMPORTANT: Routes MUST be chained for type inference to work. Without chaining, the client cannot infer route types.**
|
|
483
|
+
|
|
484
|
+
```ts
|
|
485
|
+
// Server: routes MUST be chained to preserve types
|
|
486
|
+
const route = app
|
|
487
|
+
.post('/posts', zValidator('json', schema), (c) => {
|
|
488
|
+
return c.json({ ok: true }, 201)
|
|
489
|
+
})
|
|
490
|
+
.get('/posts', (c) => {
|
|
491
|
+
return c.json({ posts: [] })
|
|
492
|
+
})
|
|
493
|
+
export type AppType = typeof route
|
|
494
|
+
|
|
495
|
+
// Client: use hc() with the exported type
|
|
496
|
+
import { hc } from 'hono/client'
|
|
497
|
+
import type { AppType } from './server'
|
|
498
|
+
|
|
499
|
+
const client = hc<AppType>('http://localhost:8787/')
|
|
500
|
+
const res = await client.posts.$post({ json: { title: 'Hello' } })
|
|
501
|
+
const data = await res.json() // fully typed
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Type utilities:
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
import type { InferRequestType, InferResponseType } from 'hono/client'
|
|
508
|
+
|
|
509
|
+
type ReqType = InferRequestType<typeof client.posts.$post>
|
|
510
|
+
type ResType = InferResponseType<typeof client.posts.$post, 200>
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## Helpers
|
|
516
|
+
|
|
517
|
+
Helpers are utility functions imported from `hono/<helper-name>`:
|
|
518
|
+
|
|
519
|
+
```ts
|
|
520
|
+
import { getConnInfo } from 'hono/conninfo'
|
|
521
|
+
import { getCookie, setCookie, deleteCookie } from 'hono/cookie'
|
|
522
|
+
import { css, Style } from 'hono/css'
|
|
523
|
+
import { createFactory } from 'hono/factory'
|
|
524
|
+
import { html, raw } from 'hono/html'
|
|
525
|
+
import { stream, streamText, streamSSE } from 'hono/streaming'
|
|
526
|
+
import { testClient } from 'hono/testing'
|
|
527
|
+
import { upgradeWebSocket } from 'hono/cloudflare-workers' // or other adapter
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Available helpers: Accepts, Adapter, ConnInfo, Cookie, css, Dev, Factory, html, JWT, Proxy, Route, SSG, Streaming, Testing, WebSocket.
|
|
531
|
+
|
|
532
|
+
For details, use `npx hono docs /docs/helpers/<helper-name>`.
|
|
533
|
+
|
|
534
|
+
### Factory
|
|
535
|
+
|
|
536
|
+
Use `createFactory` to define `Env` once and share it across app, middleware, and handlers:
|
|
537
|
+
|
|
538
|
+
```ts
|
|
539
|
+
import { createFactory } from 'hono/factory'
|
|
540
|
+
|
|
541
|
+
const factory = createFactory<Env>()
|
|
542
|
+
|
|
543
|
+
// Create app (Env type is inherited)
|
|
544
|
+
const app = factory.createApp()
|
|
545
|
+
|
|
546
|
+
// Create middleware (Env type is inherited, no need to pass generics)
|
|
547
|
+
const mw = factory.createMiddleware(async (c, next) => {
|
|
548
|
+
await next()
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
// Create handlers separately (preserves type inference)
|
|
552
|
+
const handlers = factory.createHandlers(logger(), (c) => c.json({ message: 'Hello' }))
|
|
553
|
+
app.get('/api', ...handlers)
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Best Practices
|
|
559
|
+
|
|
560
|
+
- Write handlers inline in route definitions for proper type inference of path params.
|
|
561
|
+
- Use `app.route()` to organize large apps by feature, not Rails-style controllers.
|
|
562
|
+
- Use `createFactory()` to share Env type across app, middleware, and handlers.
|
|
563
|
+
- Use `c.set()`/`c.get()` to pass data between middleware and handlers.
|
|
564
|
+
- Chain validators for multiple request parts (param + query + json).
|
|
565
|
+
- Export app type for RPC: `export type AppType = typeof routes`
|
|
566
|
+
- Use `app.request()` for testing — no server startup needed.
|
|
567
|
+
|
|
568
|
+
## Adapters
|
|
569
|
+
|
|
570
|
+
Hono runs on multiple runtimes. The default export works for Cloudflare Workers, Deno, and Bun. For Node.js, use the Node adapter:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
// Cloudflare Workers / Deno / Bun
|
|
574
|
+
export default app
|
|
575
|
+
|
|
576
|
+
// Node.js
|
|
577
|
+
import { serve } from '@hono/node-server'
|
|
578
|
+
serve(app)
|
|
579
|
+
```
|
|
@@ -23,20 +23,24 @@ This skill helps you use Langfuse effectively across all common workflows: instr
|
|
|
23
23
|
Follow these principles for ALL Langfuse work:
|
|
24
24
|
|
|
25
25
|
1. **Documentation First**: NEVER implement based on memory. Always fetch current docs before writing code (Langfuse updates frequently) See the section below on how to access documentation.
|
|
26
|
-
2. **CLI for Data Access**: Use `langfuse-cli` when querying/modifying Langfuse data. See the section below on how to use the CLI.
|
|
26
|
+
2. **CLI for Data Access**: Use `langfuse-cli` when querying/modifying Langfuse data. See the section below on how to use the CLI.
|
|
27
27
|
3. **Best Practices by Use Case**: Check the relevant reference file below for use-case-specific guidelines before implementing
|
|
28
|
-
4. **Use latest Langfuse versions**: Unless the user specified otherwise or there's a good reason, always use the latest version of Langfuse SDKs/APIs.
|
|
28
|
+
4. **Use latest Langfuse versions**: Unless the user specified otherwise or there's a good reason, always use the latest version of Langfuse SDKs/APIs. Even if you're only creating a plan for another agent to execute, be explicit about the exact version to use.
|
|
29
|
+
5. **If you guide the user through UI** and are unsure about a label or location, inspect the user’s screenshots or ask to see the relevant screen. Do not assume UI labels have the exact same names as API, SDK, or CLI fields.
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
## Use case specific references
|
|
32
33
|
|
|
33
34
|
- instrumenting an existing function/application: references/instrumentation.md
|
|
34
35
|
- migrating prompts from a codebase into Langfuse: references/prompt-migration.md
|
|
36
|
+
- creating a prompt or changing any part of an existing prompt, including small edits and debugging/tuning: references/prompt-engineering.md
|
|
35
37
|
- capturing user feedback (thumbs, ratings, implicit signals) as scores on traces: references/user-feedback.md
|
|
36
38
|
- further tips on using the Langfuse CLI: references/cli.md
|
|
37
|
-
- upgrading or
|
|
39
|
+
- upgrading legacy trace-level or dataset-item evaluators to observation-level or experiment evaluators: references/trace-evaluator-upgrade.md. Use the [evaluator migration guide](https://langfuse.com/faq/all/llm-as-a-judge-migration) as the primary reference.
|
|
40
|
+
- preparing an application and Langfuse project for the v4 platform migration: references/v4-project-migration.md
|
|
38
41
|
- judge calibration (LLM-as-a-Judge reliability, simple accuracy checks, advanced split-based validation, confusion matrices, and metric ingestion): references/judge-calibration.md
|
|
39
42
|
- systematic error analysis — reading traces, building failure taxonomy, deciding what to fix: references/error-analysis.md
|
|
43
|
+
- setting up CI/CD experiment gates with `langfuse/experiment-action`: references/ci-cd.md
|
|
40
44
|
- submitting feedback about this skill: references/skill-feedback.md
|
|
41
45
|
|
|
42
46
|
|
|
@@ -66,8 +70,8 @@ export LANGFUSE_PUBLIC_KEY=pk-lf-...
|
|
|
66
70
|
export LANGFUSE_SECRET_KEY=sk-lf-...
|
|
67
71
|
export LANGFUSE_BASE_URL=https://cloud.langfuse.com # example for EU cloud. For US cloud it's us.cloud.langfuse.com, and can also be a self-hosted URL. The server must always be specified in order to access Langfuse.
|
|
68
72
|
```
|
|
69
|
-
|
|
70
|
-
If not set, ask the user to set them in their shell or a `.env` file
|
|
73
|
+
If `LANGFUSE_BASE_URL` is used instead of `LANGFUSE_HOST`, run `export LANGFUSE_HOST="$LANGFUSE_BASE_URL"`.
|
|
74
|
+
If not set, ask the user to set them in their shell or a `.env` file. Keys are found in the Langfuse project under Settings -> API Keys; the user should create a project API key pair there. If they do not have a Langfuse account yet, share that they can create one for free at `https://langfuse.com/cloud`. Do not ask them to paste keys into chat for security reasons.
|
|
71
75
|
|
|
72
76
|
### Detailed CLI Reference
|
|
73
77
|
|
|
@@ -120,7 +124,7 @@ Returns a JSON response with:
|
|
|
120
124
|
- `title`: page title
|
|
121
125
|
- `source.content`: array of relevant text excerpts from the page
|
|
122
126
|
|
|
123
|
-
Search is a great fallback if you cannot find the relevant pages or need more context. Especially useful when debugging issues as all GitHub Issues and Discussions are also indexed. Responses can be large — extract only the relevant portions.
|
|
127
|
+
Search is a great fallback if you cannot find the relevant pages or need more context. Especially useful when debugging issues as all GitHub Issues and Discussions are also indexed. Responses can be large — extract only the relevant portions. Note that changelog posts may also surface here: use them only to confirm a feature exists, never to implement from — their examples may be outdated, so always implement from the docs and API/SDK reference.
|
|
124
128
|
|
|
125
129
|
### Documentation Workflow
|
|
126
130
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: langfuse-ci-cd
|
|
3
|
+
description: Set up or extend agent regression checks / gating in GitHub Actions CI/CD using `langfuse/experiment-action`.
|
|
4
|
+
metadata:
|
|
5
|
+
required_access:
|
|
6
|
+
- CODEBASE
|
|
7
|
+
- LANGFUSE_PROJECT_INTERFACE
|
|
8
|
+
- LANGFUSE_PROJECT_SCRIPT
|
|
9
|
+
- GITHUB
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Langfuse CI/CD
|
|
13
|
+
|
|
14
|
+
## Checklist
|
|
15
|
+
|
|
16
|
+
- [ ] Follow the [CI/CD docs page](https://langfuse.com/docs/evaluation/experiments/experiments-ci-cd) and the [langfuse/experiment-action README](https://github.com/langfuse/experiment-action)
|
|
17
|
+
- [ ] Inspect whether the local repository is a GitHub repo. If not, `langfuse/experiment-action` is not applicable. Follow the guide for other [CI/CD systems](https://langfuse.com/docs/evaluation/experiments/experiments-ci-cd#other-cicd-systems) instead
|
|
18
|
+
- [ ] Ask the user which [evaluators and run evaluators](https://langfuse.com/docs/evaluation/experiments/experiments-via-sdk#evaluators) they want to set up
|
|
19
|
+
- [ ] Ask the user if and when yes which regression thresholds they want to set
|
|
20
|
+
- [ ] Confirm dataset existence and shape of the dataset items before writing code with the Langfuse CLI (see `references/cli.md`)
|
|
21
|
+
- `langfuse-cli api datasets list`
|
|
22
|
+
- `langfuse-cli api dataset-items list --dataset-name <dataset name> --limit 5`
|
|
23
|
+
- [ ] Propose the user to verify the check by actually running the new CI check (e.g. by creating a pull request)
|
|
24
|
+
- [ ] If the evaluator task uses a third-party dependency, add the necessary CI steps to install them
|
|
25
|
+
|
|
26
|
+
### GitHub specific checklist
|
|
27
|
+
- [ ] Ask the user how they want the [workflow to be triggered](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows)
|
|
28
|
+
- [ ] If available, use the `gh` CLI to check secret existence / set secrets for:
|
|
29
|
+
- Langfuse credentials
|
|
30
|
+
- Credentials required by the evaluator task (e.g. OpenAI or Anthropic API keys)
|
|
31
|
+
|
|
32
|
+
## Common Issues
|
|
33
|
+
|
|
34
|
+
| Issue | Solution |
|
|
35
|
+
|-------|----------|
|
|
36
|
+
| `gh` is missing or not authenticated | Install the GitHub CLI if needed, then run `gh auth status` and `gh auth login` before using `gh secret` or `gh workflow` commands. |
|
|
37
|
+
| Local Langfuse environment variables are not set | Set `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, and `LANGFUSE_HOST` locally before using `langfuse-cli`; do not ask the user to paste secret values into chat. |
|
|
38
|
+
| Workflow secrets or action inputs are wrong | Verify `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `langfuse_base_url`, and provider secrets exist in the target repo/environment and are passed to the action step. |
|
|
39
|
+
| Forked PR cannot access secrets | GitHub restricts secret access for forked PRs. Document the limitation or choose a trusted trigger such as internal PR, trusted-branch `push`, or `workflow_dispatch`. |
|
|
40
|
+
| No default/base branch exists | Create an initial empty commit on the intended default branch before trying to verify a PR-triggered workflow. |
|
|
41
|
+
| Script fails reading dataset fields | Re-inspect the dataset items with the Langfuse CLI, check `input`, `expected_output`, and metadata, and extract fields from object-shaped outputs explicitly. |
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: langfuse-cli
|
|
3
|
+
description: Langfuse CLI usage reference — install, resource/action discovery, credentials, and common usage tips for `langfuse-cli`. Use for further tips on using the Langfuse CLI.
|
|
4
|
+
metadata:
|
|
5
|
+
required_access:
|
|
6
|
+
- LANGFUSE_PROJECT_INTERFACE
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# Langfuse CLI Reference
|
|
2
10
|
|
|
3
11
|
Documentation: https://langfuse.com/docs/api-and-data-platform/features/cli
|