Skip to content

setup ignores --help and silently performs a destructive non-idempotent reinstall #152

Description

@lcatlett

Summary

claude-smart setup does not recognize --help. Instead of printing usage or erroring on an
unknown flag, it falls through to its interactive prompts. When run non-interactively the
prompts immediately hit EOF, the defaults are silently accepted, and a full non-idempotent
reinstall executes
— rewriting config, restoring hook manifests over user edits, and
restarting services.

This makes the most destructive command in the tool the one most likely to be invoked by
accident. --help is the flag people reach for precisely because they don't know what a
command does yet.

Impact

A single claude-smart setup --help — from a script, CI, a wrapper, or an AI coding agent
inspecting the CLI — performs the following without any confirmation:

  • Rewrites ~/.reflexio/.env (announced as "removed managed Reflexio settings" then
    "configured local Reflexio defaults"). User-set values here are replaced with defaults.
  • Rewrites ~/.claude-smart/.env
  • Calls _restore_publish_hooks_from_source(), which copies the full hook manifest back over
    the installed one — silently discarding any user customization of which hooks are enabled
  • Rewrites ~/.claude-smart/install-complete
  • Re-runs the marketplace install, uv sync, and the bundled Reflexio source install
  • Restarts the backend and dashboard services

The hook-manifest restore is the most damaging: a user who had pruned hook events finds them
all silently re-enabled, with no message saying so.

Reproduction

claude-smart setup --help

Non-interactively (no tty), e.g. under timeout, a script, or a tool call.

Observed

Host (1=Claude Code, 2=Codex, 3=all, 4=OpenCode) [claude-code]: Setup mode (1=local, 2=managed Reflexio) [local]: [claude-smart setup] removed managed Reflexio settings from ~/.reflexio/.env
[claude-smart setup] configured local Reflexio defaults in ~/.reflexio/.env
Adding marketplace…✔ Marketplace 'reflexioai' already on disk — declared in user settings
Installing plugin "claude-smart@reflexioai"...✔ Plugin "claude-smart@reflexioai" is already installed (scope: user)
[claude-smart] running uv sync...
[claude-smart] installing bundled Reflexio source from ...
[claude-smart] starting dashboard build in background (~1-2 min on first install)
[claude-smart] starting backend service in background
[claude-smart] install complete. Backend started; dashboard auto-starts on session start.
Prepared claude-smart runtime at ~/.claude/plugins/cache/reflexioai/claude-smart/0.2.50.
Started claude-smart backend service.
Refreshed claude-smart dashboard service.

Both prompts print and are answered by EOF in the same line of output — the defaults are taken
with no input.

Expected

Any of:

  1. --help prints usage and exits 0 without side effects.
  2. An unrecognized flag errors and exits non-zero without side effects.
  3. When stdin is not a tty, setup refuses to run rather than accepting defaults — or requires
    an explicit --yes / --non-interactive flag to proceed.

At minimum, EOF on a prompt should abort rather than silently select the default for a
destructive operation.

Relevant source

  • src/claude_smart/cli.py_restore_publish_hooks_from_source() copies the full manifest
    from the package source over the installed one on every setup/install run, before the
    read-only pruning is conditionally applied. Any user edit to the installed manifest is lost.

Additional note on hook configuration

Related, and possibly worth a separate issue: CLAUDE_SMART_READ_ONLY=1 is currently the only
supported way to change which hooks are registered, and _command_is_publish_hook() matches
only:

hook_entry\.sh\b[\s"']+(?:codex|claude-code)[\s"']+(?:stop|session-end)\b

So read-only mode prunes Stop and SessionEnd while leaving UserPromptSubmit,
PreToolUse, and PostToolUse registered. There is no supported way to do the inverse — keep
session storage/analysis while disabling the per-prompt and per-tool-call hooks. On one machine
those three accounted for 14,358 firings against 592 stop firings in ~/.claude-smart/hook.log
(~24:1), and 339 firings in a single session.

Environment

  • claude-smart 0.2.50
  • macOS, arm64
  • Installed via the mise npm backend (npm:claude-smart), marketplace reflexioai

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions