How the /setup Command Merges New Profile Information Idempotently in AI Job Search
The /setup command achieves idempotent merges by reading existing profile files before writing, categorizing extracted content into additive changes and conflicts, and requiring explicit user confirmation before applying any updates.
The ai-job-search repository by MadsLorentzen provides a Claude-powered workflow for managing job applications. Its /setup command serves as the entry point for onboarding candidate profiles, implementing a robust idempotent merge strategy that allows users to safely re-run the command multiple times when adding new documents without risking duplicate entries or accidental overwrites.
The Three-Step Idempotent Merge Process
The idempotent behavior stems from three tightly-coupled mechanisms defined in .claude/commands/setup.md:
1. Read-Before-Write State Loading
Before processing any new documents, the command loads the current state of all seven profile skill files (e.g., 01-candidate-profile.md, 02-behavioral-profile.md, etc.) into memory. This establishes the baseline for comparison and ensures the system recognizes existing content.
According to the source code at lines 55-56, this initial read captures the complete current profile state, preventing the system from treating already-processed information as new input during subsequent runs.
2. Change-Set Construction
As documents are parsed from the documents/ directory (CVs, LinkedIn exports, diplomas), the system constructs two distinct buckets for each target file:
- Additive changes: Content that does not exist anywhere in the current file. These represent genuinely new information.
- Conflicting changes: Content that clashes with existing entries (different dates, titles, or descriptions for the same entity).
This separation, detailed at lines 37-44 in .claude/commands/setup.md, ensures that only truly novel data is proposed for insertion while potential overwrites are flagged for manual resolution.
3. Explicit Confirmation Gate
The command never writes to disk without user approval. At Step A6 (lines 66-86), the full change set is presented to the user. Additive changes are applied only after receiving a "yes" confirmation, and each conflict must be resolved individually through explicit user choice.
This confirmation gate guarantees that re-running /setup after adding new documents will only surface new additive changes, as previously merged items are already present in the read state and omitted from the proposal.
Code Implementation Example
The following Python illustration demonstrates the core idempotent logic extracted from the /setup workflow:
# 1️⃣ Load existing skill files (read-before-write)
skill_files = {
"01-candidate-profile.md": read_file(path("01-candidate-profile.md")),
"02-behavioral-profile.md": read_file(path("02-behavioral-profile.md")),
# … other skill files …
}
# 2️⃣ Parse documents from `documents/` (cv, linkedin, diplomas, …)
extracted = parse_documents(glob("documents/**/*"))
# 3️⃣ Build change sets
additive = {}
conflicts = {}
for target, content in extracted.items():
current = skill_files[target]
if content not in current: # new info → additive
additive.setdefault(target, []).append(content)
elif content_conflicts(content, current): # different info → conflict
conflicts.setdefault(target, []).append(
{"new": content, "current": current}
)
# 4️⃣ Present to user (Step A6) – only apply after explicit consent
present_changes(additive, conflicts)
if user_confirms_additive():
apply_additive_changes(additive)
resolve_conflicts_one_by_one(conflicts)
Key implementation details include:
read_file: Ensures the latest file content is in memory before any modifications.content not in current: Guarantees that only new snippets become additive changes.content_conflicts: Forces user intervention when extracted data differs from existing entries.
Target Profile Files
The /setup command maintains seven skill files that serve as the single source of truth for the candidate's profile:
| File | Role in the Idempotent Merge |
|---|---|
.claude/skills/job-application-assistant/01-candidate-profile.md |
Stores the candidate's core identity; merged idempotently from CV/LinkedIn data. |
.claude/skills/job-application-assistant/02-behavioral-profile.md |
Holds inferred behavioral traits; additive updates are labelled and only added once. |
.claude/skills/job-application-assistant/03-writing-style.md |
Captures writing-style observations extracted from cover-letter templates. |
.claude/skills/job-application-assistant/04-job-evaluation.md |
Contains calibrated evaluation signals; updated only with new evidence. |
.claude/skills/job-application-assistant/05-cv-templates.md |
Stores reusable CV snippets; additive entries are created from new drafts. |
.claude/skills/job-application-assistant/06-cover-letter-templates.md |
Holds distinct cover-letter structures; merged without duplication. |
.claude/skills/job-application-assistant/07-interview-prep.md |
Accumulates STAR candidates; conflict-free because only new achievements are added. |
Summary
- The
/setupcommand implements idempotent merges through a read-before-write pattern that prevents duplicate processing of existing content. - Change-set construction separates new information (additive) from potential overwrites (conflicts), ensuring data integrity.
- An explicit confirmation step (Step A6) requires user approval before any file modifications, making the command safe to re-run after adding new documents.
- Seven profile skill files in
.claude/skills/job-application-assistant/serve as the persistent state, progressively enriched without duplication through this architecture.
Frequently Asked Questions
What happens if I run /setup twice with the same documents?
Running /setup a second time with identical documents produces no changes. The read-before-write mechanism loads the current profile state and recognizes that the extracted content already exists in the skill files, resulting in empty additive and conflict buckets. Since no new changes are detected, the command presents nothing for confirmation and terminates without modifying any files.
How does the system detect conflicts versus new content?
The system uses two distinct checks during change-set construction. First, it checks content not in current to identify genuinely new information for the additive bucket. If content matches an existing entry but differs in specific fields (dates, titles, descriptions), the content_conflicts function flags it for the conflicts bucket. This dual-check approach ensures novel data is proposed for addition while existing data that has changed externally is surfaced for manual resolution.
Can I automate the confirmation step for CI/CD pipelines?
No, the explicit confirmation step at Step A6 in .claude/commands/setup.md is designed as a mandatory gate requiring interactive user input. The command requires manual confirmation ("yes") for additive changes and individual resolution of each conflict. This design prioritizes data integrity over automation, ensuring human review of all profile modifications before they are persisted to the skill files.
Where are the profile files stored after merging?
Merged profile information is stored in the seven Markdown files located in .claude/skills/job-application-assistant/, specifically 01-candidate-profile.md through 07-interview-prep.md. These files constitute the persistent single source of truth for the candidate's profile, with each file serving a distinct purpose from core identity to interview preparation materials.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →