Type-safe
defineSurvey returns a typed Survey. Zod schemas per question. Branching is a TS function, not a DSL.
Type-safe, agent-friendly, open source. Define a survey in five lines. Run it interactively or pipe answers from an agent. No backend required.
$ bunx @crafter/survey-cli take onboarding ◇ Welcome - quick onboarding [1/5] What best describes you? ◆ dev [2/5] What do you ship with? ◆ next, astro [3/5] What is your biggest blocker? │ Keeping feedback structured across humans and agents. [4/5] Want a followup email? ◆ yes [5/5] Email? │ hunter@crafterstation.com ┌ Summary ─────────────────────────────┐ │ role: dev · stack: next, astro │ └ saved ~/.survey-cli/onboarding/*.json ┘
$ bunx @crafter/survey-cli take onboarding ◇ Welcome - quick onboarding [1/5] What best describes you? ◆ dev [2/5] What do you ship with? ◆ next, astro [3/5] What is your biggest blocker? │ Keeping feedback structured across humans and agents. [4/5] Want a followup email? ◆ yes [5/5] Email? │ hunter@crafterstation.com ┌ Summary ─────────────────────────────┐ │ role: dev · stack: next, astro │ └ saved ~/.survey-cli/onboarding/*.json ┘
Type-safe end-to-end. Branching via next(). Validation via Zod. No DSL.
// surveys/onboarding.ts
import { defineSurvey, q } from "@crafter/survey-cli/define"
import { z } from "zod"
export default defineSurvey({
id: "onboarding",
title: "Welcome",
questions: [
q.select("role", "Role?", ["dev", "designer", "founder"]),
q.multiselect("stack", "Stack?", ["next", "astro", "remix"]),
q.text("blocker", "Biggest blocker?", { schema: z.string().min(10) }),
q.confirm("followup", "Want followup?", {
next: (a) => a.followup ? "email" : null,
}),
q.text("email", "Email?", {
schema: z.string().email(),
skipIf: (a) => !a.followup,
}),
],
}) defineSurvey returns a typed Survey. Zod schemas per question. Branching is a TS function, not a DSL.
Pipe JSON via stdin. Schema introspectable. Validation errors structured. CI-ready.
MIT. No telemetry. No backend. Responses live on your disk.
Responses persist to ~/.survey-cli/<survey-id>/<timestamp>.json. Override with SURVEY_CLI_HOME=/path.
| Command | What it does |
|---|---|
| survey list | list surveys in ./surveys |
| survey schema <id> | print survey schema as JSON |
| survey take <id> | interactive (humano en TTY) |
| survey take <id> --answers '{...}' | agent batch |
| echo '{...}' | survey take <id> --json | agent batch via stdin |
| survey take <id> --yes | skip summary confirm |
| survey responses <id> | list saved responses |
| survey responses <id> --export csv | export all to CSV |
| survey responses <id> show <ts> | show one response by timestamp |
MIT licensed. Made by Crafter Station.