@crafter/survey-cli · v0.0.1

Surveys, from your terminal.

Type-safe, agent-friendly, open source. Define a survey in five lines. Run it interactively or pipe answers from an agent. No backend required.

View on GitHub →
survey take onboarding
TTY
$ 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 ┘
survey take onboarding
TTY
$ 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 ┘

Define a survey.

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,
    }),
  ],
})

Type-safe

defineSurvey returns a typed Survey. Zod schemas per question. Branching is a TS function, not a DSL.

Agent-friendly

Pipe JSON via stdin. Schema introspectable. Validation errors structured. CI-ready.

Open source

MIT. No telemetry. No backend. Responses live on your disk.

Commands.

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

Ask, don't form.

MIT licensed. Made by Crafter Station.