Run surveys from your terminal. Agent-friendly, type-safe, OSS.
bunx @crafter/survey-cli take onboardingbun add -g @crafter/survey-cli
# or run ad-hoc:
bunx @crafter/survey-cli <cmd>// 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,
}),
],
})Type-safe end-to-end. Branching via next(). Validation via Zod. No DSL.
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 timestampResponses persist to ~/.survey-cli/<survey-id>/<timestamp>.json. Override with SURVEY_CLI_HOME=/path.
| Mode | When | How |
|---|---|---|
| Interactive | Humano en TTY | survey take <id> |
| Agent batch | Pipeline / IA agent / CI | survey take <id> --answers '{...}' |
| Resume | Cancelaste a la mitad | survey take <id> (auto-detecta in-progress) |
Two Claude Code skills planned to ship alongside this CLI:
/survey-create— generatedefineSurvey({...})from a prompt ("post-event feedback, 6 questions")/survey-fill— agent fills--answersfrom local context (CLAUDE.md, env, vault) and submits
Track in issues.
V1 (current) — local-first, no backend, JSON storage.
Future — hosted backend, web dashboard, AI form builder. See shaping.md.
MIT © Railly Hugo
