Skip to content

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

@griffinwork40

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions