Skip to content

feat(permission): prompt for confirmation in manual mode - #90

Merged
itayinbarr merged 2 commits into
itayinbarr:mainfrom
marek2901:manual-permission-prompt
Aug 22, 2026
Merged

feat(permission): prompt for confirmation in manual mode#90
itayinbarr merged 2 commits into
itayinbarr:mainfrom
marek2901:manual-permission-prompt

Conversation

@marek2901

Copy link
Copy Markdown
Contributor

Summary

In manual permission mode, little-coder now prompts the user before executing any shell command instead of blocking outright.

Behavior

Mode Before After
auto (default) Block non-whitelisted commands Unchanged
accept-all Allow all commands Unchanged
manual Block non-whitelisted commands Prompt for every command

In manual mode:

  1. Show the exact command to execute
  2. Ask: Execute this command?
  3. User confirms (y) → execute
  4. User cancels (n) → block with "command cancelled by user"

Usage

export LITTLE_CODER_PERMISSION_MODE=manual
little-coder

Implementation

  • Minimal change: reuse existingctx.ui.confirm() API
  • No new dependencies or abstractions
  • All 536 tests pass

Files changed

  • .pi/extensions/permission-gate/index.ts — add confirmation prompt for manual mode
  • .pi/extensions/permission-gate/permission.test.ts — add tests for manual mode
  • README.md — updateLITTLE_CODER_PERMISSION_MODE table

…locking

manual permission mode now asks the user before executing each shell
command instead of blocking outright. Shows the command and waits for
y/N confirmation. auto and accept-all modes unchanged.

- Add ctx.ui.confirm() prompt before shell execution in manual mode
- User can approve (y) or cancel (n) each command
- Update README to document new manual mode behavior
- Add tests for confirm/cancel/prompt-for-all-cmds
@marek2901
marek2901 force-pushed the manual-permission-prompt branch from 9ee494e to f2331f3 Compare August 15, 2026 23:53

@itayinbarr itayinbarr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. manual mode has been the odd one out since it landed: it blocked exactly what auto blocks and only changed the wording of the refusal, which is not what anyone reading "manual" expects. Prompting per command is the behavior the name promises.

I checked the parts that worried me before approving:

  • ctx.ui.confirm is on the plain ExtensionContext in pi 0.83 (ui: Pick<ExtensionUIContext, "select" | "confirm" | "input" | "notify">), so the tool_call handler really does have it. Not every session does: pi's noOpUIContext.confirm resolves false, so a headless run in manual mode refuses everything. That is the right default for a mode whose whole point is a human in the loop, and it cannot bite sub-coders because buildChildEnv pins children to LITTLE_CODER_PERMISSION_MODE=auto.
  • Confirming skips isSafeBash entirely, including for whitelisted commands. Correct: in manual mode the user is the whitelist. write-guard is a separate tool_call handler and still runs, so a confirmed cat > existing.py is still caught by the guard that exists for that.
  • Full suite green on your branch (633 passed), typecheck clean, and the branch is not behind main.

Thanks for keeping it to ctx.ui.confirm rather than inventing an abstraction.

@itayinbarr
itayinbarr merged commit b8f6a6d into itayinbarr:main Aug 22, 2026
itayinbarr pushed a commit that referenced this pull request Aug 22, 2026
…compacted" (#109, #91)

The context watchdog reported its result through the ctx captured at the turn
that fired the compaction. pi invalidates the whole extension runtime on
dispose(), so ctx.ui and pi.sendUserMessage() throw from that point on, and pi
invokes the compaction callbacks from a floating promise: the throw became an
unhandled rejection and a hard exit 1. Reproduced end to end against a live
backend, with heinrichI's exact stack trace, and verified fixed on the same run.

The same callback also treated every rejection as "compaction is futile, pause".
"Already compacted" means someone else's compaction landed first, so the context
is compacted and only our call lost the race; pausing there stranded a mid-task
run at the prompt. It now resumes like a success, a cancellation is silent, and
only a real failure still pauses. An outstanding-call counter stops a turn
boundary mid-compaction from starting the second call that loses that race.

Also fixes the write-guard regression in #107 (a device redirect butted straight
up against ;, &&, ||, | or a closing paren), and merges #90 and #105.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KviAutUdC2iacq59kUcuxJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants