Skip to content

Intelligent prs init & Migration Flow

Date: 2026-03-20 Status: Implemented Scope: packages/cli, packages/importer

Problem

The current prs init creates config + template files but only shows a passive hint when existing AI instruction files are detected. Migration requires separate manual steps (prs import, prs init --migrate) that are disconnected from the init flow. Users must figure out the migration path themselves.

Goals

  1. Detect existing instruction files and offer migration inline during init
  2. Support static import (fast, deterministic) and AI-assisted migration (skill + kick-start prompt)
  3. Multi-file import with modular .prs output (recommended project structure)
  4. Minimize manual work — guide the user step by step
  5. Safe for CI/CD with explicit opt-in flags

Non-Goals

  • Reverse sync (importing manual changes from compiled output back to .prs) — future feature
  • LLM API calls from CLI — we generate prompts, not call models
  • Auto-compile after init — user reviews .prs first

Design

1. Command Flow & Decision Tree

prs init
  ├─ promptscript.yaml exists? (no --force)
  │   YES → "Already initialized"
  │         → hint: "Use --force to reinitialize"
  │         → exit(2)
  ├─ Detect: project info, AI tools, migration candidates
  ├─ Migration candidates found?
  │   │
  │   ├─ YES → Gateway prompt:
  │   │   "Found existing instruction files:"
  │   │   "  CLAUDE.md (3.4 KB, Claude Code)"
  │   │   "  .cursorrules (1.8 KB, Cursor)"
  │   │
  │   │   ? How would you like to start?
  │   │     > 🔄 Migrate existing instructions to PromptScript
  │   │       ✨ Fresh start (ignore existing files)
  │   │
  │   └─ NO → straight to Fresh Start flow
  ├─ FRESH START flow:
  │   1. Standard init prompts (name, registry, targets)
  │   2. Create promptscript.yaml + scaffold .promptscript/project.prs
  │   3. Install PromptScript skill to all targets
  │   4. "Next: use /promptscript in your AI tool to fill in project.prs"
  └─ MIGRATE flow:
      1. Standard init prompts (name, registry, targets)
      2. Create promptscript.yaml
      3. Migration strategy prompt:
         ? How do you want to migrate?
           > 📋 Static import (fast, deterministic)
             🤖 AI-assisted migration (installs skill + generates prompt)
      ├─ STATIC:
      │   1. Git safety check (warn if no git repo)
      │   2. Ask: "Backup to .prs-backup/?" (default: no if git, yes if no git)
      │   3. Select files to import (checkbox, all pre-checked)
      │   4. Run multi-file import → modular .prs structure
      │   5. Show confidence report
      │   6. Install PromptScript skill to targets
      │   7. "Next: review .prs files, then prs compile"
      └─ AI-ASSISTED:
          1. Git safety check (warn if no git repo)
          2. Ask: "Backup to .prs-backup/?" (default: no if git, yes if no git)
          3. Create scaffold .promptscript/project.prs
          4. Install PromptScript skill to targets (before compile)
          5. Generate kick-start prompt (file list + migration instructions)
          6. Copy to clipboard / display in terminal
          7. Save to .promptscript/migration-prompt.md
          8. "Next: paste this prompt in your AI tool"

2. Multi-file Static Import & Modular Output

Import pipeline

Detected files: CLAUDE.md, .cursorrules, copilot-instructions.md
                    │           │              │
                    ▼           ▼              ▼
              importFile()  importFile()   importFile()
                    │           │              │
                    ▼           ▼              ▼
              ScoredSection[] per file (with source attribution)
              mergeSections() — group by target block type
              Deduplicate — exact match after whitespace normalization
              Emit modular .prs structure

Output structure

.promptscript/
  project.prs        # Entry: @meta, @inherit, @use directives, @identity
  context.prs        # @context (merged from all sources)
  standards.prs      # @standards (merged, categorized)
  restrictions.prs   # @restrictions (union of all sources)
  commands.prs       # @shortcuts + @knowledge (if found, grouped as supplementary content)

Files are only emitted if they contain content. If no @shortcuts or @knowledge sections are found, commands.prs is not created. Users can reorganize the modular structure after import.

project.prs contains @use directives pointing to the modular files:

@meta {
  id: "my-project"
  syntax: "1.4.7"
}

@use ./context
@use ./standards
@use ./restrictions
@use ./commands

@identity {
  """
  [merged identity from primary source]
  """
}

Merge rules per block type

Block Strategy Conflict resolution
@identity Pick longest (highest character count after trim) Others added as # REVIEW: alt from <source>
@context Union structured fields Deduplicate identical entries
@standards Merge by category key Concatenate arrays, source comment on conflicts
@restrictions Full union Restrictions are additive — no conflicts
@shortcuts Merge all Same command name → keep longer, comment shorter
@knowledge Concatenate Source attribution headers between sections

Confidence reporting

Sections below 50% confidence get # REVIEW: low confidence — verify this mapping in output.

Import Summary:
  CLAUDE.md        → 5 sections (87% confidence)
  .cursorrules     → 3 sections (82% confidence)
  copilot-instr.md → 4 sections (85% confidence)

  Merged: 8 unique sections (3 deduplicated)
  Overall confidence: 84%

3. AI-Assisted Migration (Skill + Kick-start Prompt)

The PromptScript CLI ships a built-in skill (packages/cli/skills/promptscript/SKILL.md) that is normally auto-injected during prs compile. For migration, we install it before compile to avoid overwriting existing instruction files.

Kick-start prompt template

The generated prompt does NOT include full file contents (they're on disk — AI can read them). It includes:

Migrate my existing AI instructions to PromptScript.

I've just initialized PromptScript in this project. The following
instruction files need to be migrated to .prs format:

- CLAUDE.md (3.4 KB, Claude Code)
- .cursorrules (1.8 KB, Cursor)
- .github/copilot-instructions.md (2.1 KB, GitHub Copilot)

Use the /promptscript skill for the PromptScript language reference.

Steps:

1. Read each file listed above
2. Analyze the content and map to PromptScript blocks
3. Generate a modular .prs structure in .promptscript/:
   - project.prs (entry: @meta, @identity, @use directives)
   - context.prs (@context)
   - standards.prs (@standards)
   - restrictions.prs (@restrictions)
   - commands.prs (@shortcuts, @knowledge)
4. Deduplicate overlapping content across files
5. Run: prs validate --strict
6. Run: prs compile --dry-run

Clipboard delivery

  • macOS: pbcopy
  • Linux: xclip -selection clipboard or xsel --clipboard
  • Windows: clip
  • Fallback: print to terminal + "Could not copy to clipboard"
  • Always save to .promptscript/migration-prompt.md

Tool-specific next steps

After prompt generation, show invocation hints per detected target:

Invoke the PromptScript skill in your AI tool:
  Claude Code: /promptscript
  Cursor: /promptscript
  GitHub Copilot: /promptscript

4. CLI Flags & Non-interactive Mode

prs init flags

prs init                          # Interactive — gateway choice if files detected
prs init -y                       # Non-interactive, safe defaults, skip migration
prs init -y --auto-import         # Non-interactive + static import of detected files
prs init -i                       # Force interactive even with all args provided
prs init -f                       # Force reinitialize
prs init --backup                 # Create .prs-backup/
prs init -m, --migrate            # DEPRECATED → deprecation notice, installs skill

The --migrate flag stays for backward compatibility with a deprecation warning:

⚠ --migrate is deprecated. Use interactive mode: prs init
  The migration flow is now built into the standard init process.

prs migrate command

Alias/shortcut to the init migration path:

prs migrate                       # Alias → prs init (enters migrate flow)
prs migrate --static              # Non-interactive: imports ALL detected files without prompting
prs migrate --llm                 # Non-interactive: generates kick-start prompt to stdout
prs migrate --files <f1> <f2>     # Selective: import only specified files

--static imports all detected candidates without confirmation (equivalent to prs init -y --auto-import). Use --files for selective non-interactive import. --llm pre-selects the AI-assisted path and copies the prompt to clipboard (falls back to stdout if clipboard unavailable).

Behavior depends on whether promptscript.yaml exists:

  • No promptscript.yaml: Runs initCommand() with the migrate flow pre-selected (skips gateway prompt).
  • promptscript.yaml exists: Runs migration flow only (skips init prompts — config already exists). Detects migration candidates and offers static/AI-assisted import into the existing .promptscript/ directory. This allows users to add migration to an already-initialized project without --force.

Reverse sync (re-importing manual edits from compiled output) is out of scope — future feature.

Non-interactive behavior matrix

Flags Files detected? Behavior
-y No Standard init, scaffold project.prs, install skill
-y Yes Standard init, scaffold project.prs, install skill, hint about migration
-y --auto-import No Standard init (nothing to import)
-y --auto-import Yes Standard init + static multi-file import → modular .prs
-y --auto-import --backup Yes Same + backup to .prs-backup/
(no flags) No Interactive fresh start
(no flags) Yes Interactive gateway: migrate vs fresh start

Exit codes

Code Meaning
0 Success
1 General failure
2 Already initialized (without --force)

Git safety check

Before migration (static or AI-assisted):

  • If not a git repo → warn, default backup to "yes"
  • If git repo → default backup to "no"

Backup directory: Uses timestamped subdirectory: .prs-backup/<ISO-timestamp>/. Multiple backups can coexist without collision. The @use directive convention is without file extension (e.g., @use ./context resolves to ./context.prs).

Stdout vs stderr

  • Human-readable output → stderr (spinners, summary, hints)
  • Kick-start prompt → stdout only in non-interactive mode (pipe-friendly: prs migrate --llm 2>/dev/null | pbcopy). In interactive mode, the prompt is copied to clipboard and/or saved to file — not emitted to stdout (which would conflict with Inquirer prompts).
  • Structured output → stdout with --format json
  • All Inquirer prompts use stderr as their output stream (Inquirer supports this via the output option).

5. Fresh Start: Skill Installation

For the "Fresh start" path (no migration), after creating config and scaffold files, prs init installs the built-in PromptScript skill directly to all target directories. This allows the AI tool to immediately help the user edit .prs files using /promptscript — without needing prs compile first (which would generate output from a placeholder template).

Once the user finishes editing .prs files, they run prs compile which generates output AND auto-injects the skill (normal compile behavior).

6. Enhanced Migration Candidate Detection

The AIToolsDetection.migrationCandidates type changes from string[] to enriched objects:

interface MigrationCandidate {
  path: string;
  format: DetectedFormat; // 'claude' | 'github' | 'cursor' | 'generic'
  sizeBytes: number;
  sizeHuman: string; // "3.4 KB"
  toolName: string; // "Claude Code", "Cursor", etc.
}

Format detection mapping: The importer's DetectedFormat is currently 'claude' | 'github' | 'cursor' | 'generic'. Files without a dedicated parser (AGENTS.md, OPENCODE.md, GEMINI.md, .windsurfrules, .clinerules, AI_INSTRUCTIONS.md, AI.md) fall through to 'generic'. The generic parser handles markdown-based instruction files adequately for static import. Expanding DetectedFormat with additional parsers is future work and not required for this design.

Ambiguous file ownership: Some files (e.g., AGENTS.md) appear in detection patterns for multiple tools (Factory, Codex, Amp). The toolName field uses the first matching tool pattern from AI_TOOL_PATTERNS (ordered by specificity). The format field is independent — determined by the importer's detectFormat(), not by the AI tool detection.

This is an internal CLI interface change — no public API impact.


Implementation Phases

Phase 1: Foundation utilities (no breaking changes)

New files:

  • packages/cli/src/utils/clipboard.ts — cross-platform clipboard
  • packages/cli/src/utils/backup.ts.prs-backup/ creation + git repo detection
  • packages/cli/src/utils/migration-prompt.ts — kick-start prompt generator

Tests:

  • packages/cli/src/__tests__/clipboard.spec.ts
  • packages/cli/src/__tests__/backup.spec.ts
  • packages/cli/src/__tests__/migration-prompt.spec.ts

Phase 2: Multi-file import in @promptscript/importer

New files:

  • packages/importer/src/merger.ts — section dedup + merge by block type
  • packages/importer/src/multi-importer.ts — batch import → modular .prs output

Modified files:

  • packages/importer/src/emitter.ts — source attribution comments, modular emit
  • packages/importer/src/index.ts — export new functions

Tests:

  • packages/importer/src/__tests__/merger.spec.ts
  • packages/importer/src/__tests__/multi-importer.spec.ts

Phase 3: Enhanced init command

Modified files:

  • packages/cli/src/commands/init.ts — gateway choice, migrate flow, skill install for fresh start, kick-start prompt generation
  • packages/cli/src/types.ts — add import flag to InitOptions
  • packages/cli/src/utils/ai-tools-detector.ts — enrich MigrationCandidate with size, format, toolName

Tests:

  • packages/cli/src/__tests__/init-migrate.spec.ts (new)
  • packages/cli/src/__tests__/init-command.spec.ts (update)

Phase 4: prs migrate command

New files:

  • packages/cli/src/commands/migrate.ts — thin wrapper delegating to init

Modified files:

  • packages/cli/src/cli.ts — register migrate command + --import flag on init, deprecation for --migrate

Tests:

  • packages/cli/src/__tests__/migrate-command.spec.ts

Phase 5: Documentation

Modified files:

  • packages/cli/skills/promptscript/SKILL.md — update CLI commands section
  • New migration guide (location TBD based on docs structure)

Dependency graph

Phase 1 (utils) ─────────────┐
                              ├─→ Phase 3 (init) ─→ Phase 4 (migrate) ─→ Phase 5 (docs)
Phase 2 (multi-import) ──────┘

Phases 1 and 2 are independent and can be parallelized.

Scope summary

Phase New source files Modified source files New test files
1 3 0 3
2 2 2 2
3 1 (init-migrate test) 3 update 1 existing test
4 2 (command + test) 1
5 0 2 0
Total 8 8 5 new + 1 update

Error Handling

Scenario Handling
File detected but unreadable Skip with warning, continue with remaining files
Import produces 0 sections Skip with warning: "Could not parse X"
All sections LOW confidence (<50%) Warn: "Low confidence — consider AI-assisted migration"
promptscript.yaml exists without --force Exit with code 2
User cancels (Ctrl+C) Catch ExitPromptError, clean exit
Clipboard unavailable Fallback to terminal display
Not a git repo + no backup Warn and default backup prompt to "yes"

Backward Compatibility

  • prs init -y behavior unchanged (scaffold, no auto-import)
  • prs init --migrate continues to work (installs skill) with deprecation notice
  • prs import <file> single-file import unchanged
  • New behavior only activates in interactive mode when candidates detected, or with explicit --import flag
  • Exit code change: "Already initialized" previously exited with code 0 (warn + return). Now exits with code 2. This is a breaking change for scripts that check exit codes — document in release notes.