Skip to content

Resumable prompts for agent environments #533

@posva

Description

@posva

Problem

Interactive CLIs built on prompts (clack, prompts, inquirer, etc) work great for humans but break down in non-TTY environments like CI, and increasingly, AI coding agents. The CLI usually hangs forever and just fails.

Non interactive CLIs can be made to work by just passing the right flags, which are auto discovered by agents: run cli without args -> error, _run cli with --help -> pick the right flags, run cli with flags -> success.
But more complex flows with branching, dependent questions, or many steps can't realistically be flattened into one invocation.

Proposal: resumable CLIs

Make interactive flows resumable. The idea:

  1. On first run in a non-TTY environment, the CLI writes the current question (and accumulated state) to a file, outputs the next steps to the stdout, and exit with a non-zero code.
  2. The agent reads the file, fills in the answer, and re-runs the CLI pointing at the same state file.
  3. The CLI reruns from the start, automatically answering questions using the state file, and stooping at the next question. This continues until all questions are answered and the CLI can complete successfully.

The key claim is that this can be done while keeping mostly the same codebase: the library usage stays the same.

Considerations

  • State file conflicts when the CLI is run multiple times in the same dir. Solvable by passing a path explicitly (--state-file /tmp/mycli-state-1234.json) that is generated if not provided (first run).
  • Side effects (e.g. opening a PR, publishing a package) must be wrapped in some kind of transaction so they only run once across resumed invocations. See once
  • Running less times: to avoid re-running the CLI on each question, it could be possible to batch questions together.

Prior art / proof of concept

I have a working POC at https://github.com/posva/clack/tree/feat/agent-mode. Nothing in it is meant for reuse: it's 100% vibecoded and leans on a local state file. But it exists and validates the idea on real workflows:

Both work without changing the underlying CLI logic, only the prompt runtime. That being said, I did adapt to use batch() and once().

What I'd like to discuss

  • Is clack the right place for this? Do you see value in this proposal? I think it makes more sense to improve the existing library than to create a new one
  • What should the state file format look like? In my testing, JSON was working well without any extra instructions
  • What's the right convention for the resume protocol: env var, option, auto-detect non-TTY?
  • Any thoughts on the side-effects/transaction problem? Any better idea than once()?
  • Alternatives to batch() that can keep the code mostly the same but avoid re-running the CLI on each question
  • Did anyone else try to solve this problem?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    Needs triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions