Where Are Skill Files Located and What Is Their Purpose in the ai-job-search Repository
Skill files reside in .claude/skills/ for Claude-style workflow automation and .agents/skills/ for portal-specific scraping, serving as modular specifications that define job-search capabilities through YAML metadata and step-by-step instructions.
The MadsLorentzen/ai-job-search repository implements a thin-pointer architecture described in AGENTS.md to organize its automation logic. Understanding where skill files are located and what purpose they serve is essential for extending the job-search workflow or troubleshooting agent behavior. These files act as the single source of truth for all AI-driven capabilities in the project.
Skill Files Location: The Two Primary Directories
The repository organizes reusable skill definitions in two distinct locations, each serving a different layer of the automation stack.
Claude-Style Workflow Directory (.claude/skills/)
Located at the repository root, the .claude/skills/ directory houses skills that drive the core job-search workflow orchestration. Each subdirectory—such as upskill/, job-scraper/, or job-application-assistant/—contains a mandatory SKILL.md file at /.claude/skills/<skill-name>/SKILL.md. These files define high-level capabilities that Claude (or compatible agents) execute, including application assistance and skill improvement tasks.
Key files in this directory include:
.claude/skills/job-application-assistant/SKILL.md– Defines the core job-application workflow..claude/skills/job-scraper/SKILL.md– Orchestrates portal-specific scrapers..claude/skills/upskill/SKILL.md– Handles up-skilling and professional development tasks.
Portal-Specific Agent Directory (.agents/skills/)
Parallel to the Claude directory, .agents/skills/ contains portal-specific implementations for scraping job boards like LinkedIn and Indeed. Following the pattern /.agents/skills/<portal>/SKILL.md, these skills expose a minimal command-line interface that other agents invoke to perform targeted searches on specific platforms. For example, .agents/skills/linkedin/SKILL.md (when present) provides the CLI specification for LinkedIn job searches.
What Skill Files Are Used For
The purpose of each SKILL.md extends beyond simple documentation; it functions as an executable contract between human intent and agent behavior. Every file begins with YAML front-matter declaring a name, description, and optionally an allowed-tools list that restricts which scripts or binaries the skill may invoke. This whitelist approach ensures that even if an agent misinterprets instructions, it cannot execute arbitrary code outside the predefined toolset.
The body of the file contains the actual step-by-step instructions that agents follow. According to the repository's thin-pointer architecture, these canonical definitions prevent configuration duplication across the codebase. When you need to modify how the system handles job applications, you edit .claude/skills/job-application-assistant/SKILL.md, and all dependent agents automatically pick up the changes.
Automatic Discovery and Validation via tools/lint_skills.py
The repository ensures skill integrity through tools/lint_skills.py, a helper script that automatically discovers all SKILL.md files under both .claude/skills/ and .agents/skills/. The script globs these directories, parses the YAML front-matter to validate schema compliance, and verifies that every entry in allowed-tools references an actual executable file in the repository.
This validation guarantees that skills are well-formed and that the automation toolchain can safely invoke them without encountering missing dependencies. Running the linter from the repository root produces a concise status report:
python tools/lint_skills.py
# → lint_skills: OK (3 skills, 15 commands, settings.json)
Reading and Executing Skill Files Programmatically
You can extract structured metadata from any skill file by parsing its YAML front-matter. The following Python snippet demonstrates how to load a skill's configuration:
import yaml
from pathlib import Path
skill_path = Path(".claude/skills/job-application-assistant/SKILL.md")
text = skill_path.read_text()
frontmatter = text.split("---")[1] # extract YAML block
metadata = yaml.safe_load(frontmatter)
print(metadata["name"]) # → "Job Application Assistant"
print(metadata["description"]) # → brief description of the skill
To invoke a portal-specific skill from the command line, navigate to the skill directory and execute its CLI wrapper:
# Invoking the LinkedIn skill
cd .agents/skills/linkedin
./cli/run-search.sh "software engineer" # runs the CLI defined for LinkedIn
Summary
- Skill files are located in
.claude/skills/for workflow automation and.agents/skills/for portal scraping. - Each
SKILL.mdfile combines YAML metadata with executable instructions to define agent capabilities. - The
allowed-toolswhitelist provides a security boundary that restricts agent execution to predefined binaries. - The
tools/lint_skills.pyscript validates all skills automatically, ensuring schema compliance and tool existence. - The architecture follows a thin-pointer design for single-source-of-truth configuration management.
Frequently Asked Questions
What is the difference between .claude/skills/ and .agents/skills/?
The .claude/skills/ directory contains high-level workflow skills like job-application-assistant that orchestrate the overall job search process, while .agents/skills/ houses portal-specific implementations such as LinkedIn or Indeed scrapers that provide command-line interfaces for targeted data extraction.
How does the allowed-tools parameter improve security?
The allowed-tools YAML key explicitly lists which binaries or scripts a skill may execute, functioning as a whitelist that prevents agents from accidentally or maliciously running unauthorized commands even if they misinterpret the skill's natural language instructions.
Can I add a new job portal without modifying existing code?
Yes. Create a new subdirectory under .agents/skills/ named after the portal, add a SKILL.md file with the required YAML front-matter, and include the portal's CLI tools. The tools/lint_skills.py script will automatically discover and validate the new skill on its next run.
How do I programmatically extract metadata from a skill file?
Parse the SKILL.md file by reading its contents, splitting on the --- delimiter to isolate the YAML front-matter, and loading that block with yaml.safe_load(). This returns a dictionary containing the skill's name, description, and allowed-tools configuration.
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 →