Skip to content

enhancement: --force silently destroys local edits to ai/ — add backup or diff #207

Description

@griffinwork40

Problem

npx aidd . --force silently destroys any local edits to ai/ without backup, diff, or confirmation.

In lib/cli-core.js, the copy step is a single whole-tree fs.copy:

// lib/cli-core.js:113–124  (copyDirectory)
const copyDirectory =
  ({ source, target }) =>
  async () => {
    try {
      await fs.copy(source, target);
    } catch (originalError) {
      throw createError({
        ...CloneError,
        cause: originalError,
        message: `Failed to copy ai/ folder from ${source} to ${target}`,
      });
    }
  };

The --force path in validateTarget (lib/cli-core.js:54–66) only checks "is ai/ present?" — it never inspects whether the contents have been modified, nor does it back anything up.

Effectively, only aidd-custom/ survives a reinstall (because aidd-custom/setup.js has skip-if-exists guards). Anything under ai/skills/, ai/commands/, ai/scaffolds/ that a user customized is gone after --force.

Why this is surfacing now

AGENTS.md and several commands explicitly encourage users to add or override skills in aidd-custom/, which is the safe extension surface. But there's no warning if a user instead edits an ai/skills/*/SKILL.md directly (which is a natural first instinct) — and on the next npx aidd . --force, those edits vanish without a trace.

There is no "update" path documented; --force is currently the only way to refresh ai/.

Suggested directions (pick one or combine)

  1. Auto-backup on --force: rename existing ai/ai.bak-<ISO-timestamp>/ before the copy. Keeps the destructive op recoverable. ~10 LoC.
  2. --diff flag: show files that would change vs. ship, without writing. Lets users see what they'd lose before committing. Could reuse listDirectoryTree + a hash compare.
  3. Refuse --force if ai/ is dirty vs. the bundled version, with an explicit override like --force --discard-local. Stops the silent-loss case while keeping the escape hatch.

Option 1 is the smallest and lowest-risk. It's also consistent with the spirit of #56 (the open issue proposing backup behavior for CLAUDE.md symlink replacement).

Expected

A user who runs npx aidd . --force after customizing ai/ should either (a) be warned and asked to confirm, or (b) have a recoverable artifact left behind.

Notes

  • The aidd-custom/ override layer is the maintainer-intended extension point — this issue is not arguing against --force as the refresh mechanism, only that the destructive step shouldn't be silent.
  • Related: [Bug] CLAUDE.md symlink creation fails when file already exists (not a symlink) #56 (backup-before-replace on symlink path) — same shape, different code path.
  • Found during a third-party audit. Citations are against paralleldrive/aidd@57758344 (current main).

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