# What Is the `modes/` Directory in CareerOps? Purpose and Architecture Explained

> Explore the CareerOps modes directory, the core of its prompt-driven system. Understand how it manages AI tasks like job evaluation and interview prep.

- Repository: [Santiago Fernández de Valderrama/career-ops](https://github.com/santifer/career-ops)
- Tags: internals
- Published: 2026-08-22

---

**The `modes/` directory serves as the central nervous system of CareerOps' prompt-driven architecture, storing static system context that every AI operation reads before executing tasks like job evaluation, pipeline processing, and interview preparation.**

The `modes/` directory forms the architectural backbone of the CareerOps repository, encapsulating all declarative prompt data that drives the application's AI capabilities. This folder implements a layered approach to prompt engineering, separating shared system logic from user customizations and locale-specific extensions. Understanding the CareerOps `modes/` directory structure is essential for customizing evaluation pipelines while maintaining consistency across updates and international markets.

## Core Architecture of the `modes/` Directory

The CareerOps `modes/` directory implements a sophisticated inheritance model that composites multiple markdown files into unified system prompts. This architecture enables safe updates—system files can change without overwriting personal data—while ensuring every operation follows identical evaluation pipelines.

### Shared System Context via [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md)

At the foundation lies [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), the **system pre-amble** automatically prepended to every mode's prompt. According to the CareerOps source code in `santifer/career-ops`, this file consolidates critical evaluation logic including:

- **Scoring rules** and rubrics for job assessment
- **Archetype taxonomy** for candidate classification
- **Spend-tier routing** logic for model selection
- **Posting-legitimacy checks** for fraud detection

By centralizing these rules in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), every mode inherits identical core reasoning, ensuring consistent evaluation standards whether you're running the `oferta` mode or the `pipeline` mode.

### User-Specific Override Layers

CareerOps supports personal customization through two optional files that layer on top of the shared context:

- **[`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md)**: Stores user-specific archetype narratives, custom formatting preferences, and personalized proof points. This file is **never edited by the system** during updates, preserving your personal data separately from core logic.

- **[`modes/_custom.md`](https://github.com/santifer/career-ops/blob/main/modes/_custom.md)**: Contains persistent procedural preferences, automation flags, and formatting tweaks that apply across all modes.

This separation enables tailored overrides without modifying core system files, allowing users to maintain customizations safely across repository updates.

### Locale and Market-Specific Extensions

For international job markets, the `modes/` directory supports localization through subdirectories such as `modes/de/`, `modes/fr/`, and `modes/zh/`. Each locale folder contains:

1. A market-specific copy of [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) with localized terminology
2. Translated mode files (e.g., [`de/oferta.md`](https://github.com/santifer/career-ops/blob/main/de/oferta.md))
3. Region-specific evaluation criteria while reusing the core rules from the root [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md)

This design allows CareerOps to scale across multiple markets while preserving a single source of truth for evaluation logic.

### Mode-Specific Task Definitions

Concrete operations reside in individually named markdown files that define specific tasks:

- **[`oferta.md`](https://github.com/santifer/career-ops/blob/main/oferta.md)**: Maps job descriptions into the A-H report structure
- **[`pipeline.md`](https://github.com/santifer/career-ops/blob/main/pipeline.md)**: Orchestrates the pre-screen → evaluation → PDF generation flow
- **[`interview/practice.md`](https://github.com/santifer/career-ops/blob/main/interview/practice.md)**: Defines interview preparation protocols
- **[`scan.md`](https://github.com/santifer/career-ops/blob/main/scan.md)**: Configures the zero-token ATS scanner using [`portals.yml`](https://github.com/santifer/career-ops/blob/main/portals.yml) data

Each mode file contains task-specific instructions concatenated after the shared context layers, making the pipeline fully declarative and reproducible.

## How Prompt Composition Works in CareerOps

The runtime composition logic resides in evaluation scripts such as `openai-eval.mjs`. This script builds the final prompt by reading files in a strict order, ensuring consistent context assembly across all entry points.

```javascript
// openai-eval.mjs – simplified excerpt
import { readFileSync } from 'fs';
import { join } from 'path';

const ROOT = process.cwd();

// 1️⃣ Load the shared system context
const shared = readFileSync(join(ROOT, 'modes', '_shared.md'), 'utf8');

// 2️⃣ Load optional user layers (if they exist)
const profilePath = join(ROOT, 'modes', '_profile.md');
const customPath  = join(ROOT, 'modes', '_custom.md');
const profile = fs.existsSync(profilePath) ? readFileSync(profilePath, 'utf8') : '';
const custom  = fs.existsSync(customPath)  ? readFileSync(customPath,  'utf8') : '';

// 3️⃣ Load the concrete mode (e.g., oferta = JD evaluation)
const mode = readFileSync(join(ROOT, 'modes', 'oferta.md'), 'utf8');

// 4️⃣ Assemble the final system prompt
const systemPrompt = [
  shared,
  profile,
  custom,
  mode,
].filter(Boolean).join('\n\n');

// 5️⃣ Send to the LLM with model resolution based on spend tier
await client.chat.completions.create({
  model: resolveModelFromSpendTier(),
  messages: [{ role: 'system', content: systemPrompt }, /* user messages */],
});

```

Running a mode from the command line uses this same composition logic:

```bash

# Evaluate a job posting (the "oferta" mode)

codex exec "node openai-eval.mjs --mode oferta --url https://example.com/jd"

# Run the scan pipeline (the "pipeline" mode)

codex exec "node openai-eval.mjs --mode pipeline --url https://example.com/feed"

```

Both commands concatenate the selected mode file after the shared context and any user overrides, ensuring identical scoring and wording across all execution paths.

## Key Files in the CareerOps `modes/` Directory

The following files constitute the complete prompt architecture:

- **[`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md)**: Core system context containing global rules, scoring rubrics, and the archetype taxonomy. This is the only mandatory file in the composition chain.

- **[`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md)**: Personal archetype narratives and proof points. This file remains untouched by system updates, preserving your career narrative across repository pulls.

- **[`_custom.md`](https://github.com/santifer/career-ops/blob/main/_custom.md)**: Persistent procedural preferences including formatting options and automation flags.

- **[`oferta.md`](https://github.com/santifer/career-ops/blob/main/oferta.md)**: Job description evaluation mode that produces structured A-H reports analyzing compensation, growth potential, and role alignment.

- **[`pipeline.md`](https://github.com/santifer/career-ops/blob/main/pipeline.md)**: Orchestration mode managing the complete flow from URL ingestion through evaluation to PDF generation.

- **[`scan.md`](https://github.com/santifer/career-ops/blob/main/scan.md)**: Zero-token ATS scanner configuration defining how to fetch and parse listings from [`portals.yml`](https://github.com/santifer/career-ops/blob/main/portals.yml).

- **[`update.md`](https://github.com/santifer/career-ops/blob/main/update.md)**: Helper mode for safely updating the shared system context while preserving user customizations in [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) and [`_custom.md`](https://github.com/santifer/career-ops/blob/main/_custom.md).

- **Locale folders (`de/`, `fr/`, `zh/`, etc.)**: Market-specific extensions containing localized [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) files and translated mode definitions.

## Summary

- The `modes/` directory in CareerOps implements a **layered prompt architecture** that composites shared logic, user overrides, and task definitions at runtime.
- **[`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md)** serves as the mandatory system pre-amble containing evaluation rules and archetype taxonomy used by all operations.
- **User isolation** is achieved through [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) (personal data) and [`_custom.md`](https://github.com/santifer/career-ops/blob/main/_custom.md) (preferences), which persist across system updates.
- **Internationalization** is supported via locale subdirectories that reuse core logic while applying market-specific terminology.
- **Prompt composition** follows a strict order in `openai-eval.mjs`: shared → profile → custom → mode, ensuring consistent AI behavior across CLI and programmatic interfaces.

## Frequently Asked Questions

### What happens if I delete [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md)?

**The system will fail to execute any mode.** The `openai-eval.mjs` script requires [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) as the foundation of every prompt. Without this file, the evaluation pipeline cannot apply scoring rules or archetype taxonomy, resulting in runtime errors when attempting to load the shared context.

### How does CareerOps prevent system updates from overwriting my customizations?

**CareerOps maintains strict separation between system files and user files.** The repository tracks [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) and mode definitions (like [`oferta.md`](https://github.com/santifer/career-ops/blob/main/oferta.md)), but [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) and [`_custom.md`](https://github.com/santifer/career-ops/blob/main/_custom.md) are typically excluded from version control or handled by the [`update.md`](https://github.com/santifer/career-ops/blob/main/update.md) helper mode. When updating, the system merges changes into [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) while preserving your personal data in the override files.

### Can I create custom modes in the `modes/` directory?

**Yes, you can create new mode files by adding markdown files to the `modes/` directory.** The `openai-eval.mjs` script dynamically loads any file specified via the `--mode` parameter. Your custom mode will automatically receive the shared context and user override layers, allowing you to define new AI operations (such as specialized screening or networking templates) using the same compositional architecture as built-in modes.

### Do locale folders completely replace the root [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md)?

**No, locale folders extend rather than replace the root context.** While [`modes/de/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/de/_shared.md) contains German-specific terminology and market rules, it typically imports or mirrors the core evaluation logic from the root [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md). This ensures that critical scoring rules remain consistent across all markets while allowing for cultural adaptations in language and local job market conventions.