v0.1.0 Node.js ≥18

Achilles CLI

A command-line interface for managing, generating, testing, and refining AI skill definitions. Build powerful AI agents with a dual-interface approach combining natural language and slash commands.

What is Achilles CLI?

Achilles CLI is a powerful tool for creating and managing skill-based AI agents. It provides a complete workflow for:

  • Creating skills - Define AI behaviors in human-readable Markdown files
  • Validating skills - Ensure skills conform to schema requirements
  • Generating code - Transform skill definitions into executable JavaScript
  • Testing and refining - Iteratively improve skills until they meet requirements

Dual Interface Design

The CLI offers two ways to interact:

Interface Best For Example
Slash Commands Fast, deterministic operations /list, /read equipment
Natural Language Complex workflows, exploration "create a validator for email addresses"

Installation

Prerequisites

  • Node.js 18.0.0 or higher
  • npm or yarn package manager
  • API key for at least one supported LLM provider

Install from npm

npm install -g @outfinityresearch/achilles-cli

Install from source

git clone https://github.com/OutfinityResearch/achilles-cli.git
cd achilles-cli/achilles-cli
npm install
npm link

Run as Ploinky Agent

The achilles-cli is a ploinky repository with the achilles-cli agent inside:

# Add to your ploinky workspace
ploinky add achilles-cli

# Run the achilles-cli agent
ploinky run achilles-cli

Environment Setup

Set an API key for at least one of the supported LLM providers:

# Choose ONE of the following providers:

# OpenAI (GPT-4o, GPT-4o-mini)
export OPENAI_API_KEY="your-api-key"

# Anthropic (Claude Sonnet, Claude Opus)
export ANTHROPIC_API_KEY="your-api-key"

# Google (Gemini 2.5 Pro, Gemini 2.5 Flash)
export GEMINI_API_KEY="your-api-key"

# OpenRouter (access to multiple models)
export OPENROUTER_API_KEY="your-api-key"

# Hugging Face
export HUGGINGFACE_API_KEY="your-api-key"

# Optional: Set default LLM mode
export ACHILLES_ORCHESTRATOR_MODE="deep"  # or "fast"

Quick Start

1. Initialize a project

mkdir my-skills-project
cd my-skills-project
achilles-cli

This creates a skills directory for your custom skills.

2. List available skills

/list all

3. Get a skill template

/template tskill

4. Create your first skill

/write my-validator tskill

Follow the prompts to define your skill's fields, validators, and presenters.

5. Validate and generate code

/validate my-validator
/generate my-validator
/test my-validator
Tip

Use /refine my-validator to automatically iterate on your skill until all tests pass.

Natural Language Usage

Beyond slash commands, you can interact with achilles-cli using natural language. The orchestrator interprets your intent and routes to the appropriate skills.

Skill Management Examples

# List and explore skills
"list all skills"
"show me the available skills"
"what skills do I have?"

# Read skill definitions
"read the equipment skill"
"show me how the user-validator is defined"
"what does the inventory skill do?"

# Create new skills
"create a new table skill called product"
"I need a validator for customer records"
"make an orchestrator that handles inventory requests"

Code Generation Examples

# Generate and test code
"generate code for the equipment skill"
"regenerate the product validator"
"test the equipment skill"
"run tests for all skills"

# Iterative improvement
"refine the equipment skill until tests pass"
"improve the product validator"
"fix the failing tests in equipment"

Skill Modification Examples

# Update specific sections
"add a phone_number field to the customer skill"
"update the validators section in equipment"
"change the status enumerator to include 'Retired'"

# Delete skills
"delete the old-validator skill"
"remove the test-skill"

Execution Examples

# Direct skill execution
"execute the list-skills skill"
"run validate-skill on equipment"

# Complex queries
"show all equipment in the Main Warehouse"
"find materials with status Available"
"list jobs assigned to area A001"
When to Use Each Interface

Use slash commands when you know exactly what you want (faster, no LLM call).
Use natural language for exploration, complex operations, or when unsure of the exact command.

Commands Overview

All slash commands provide fast, deterministic access to skill management operations without LLM interpretation.

Command Description
/list List available skills
/read Read a skill definition
/write Create or update a skill
/delete Delete a skill
/validate Validate skill structure
/template Get a blank skill template
/generate Generate executable code
/test Test generated code
/refine Iteratively improve a skill
/exec Execute a skill directly
/specs Read skill specifications
/run-tests Run test suite files

/list

/list Skill Management
Synopsis
/list [all]
Description

Lists all discovered skills in the current project. By default, shows only user-defined skills. Use the all argument to include built-in skills.

Arguments
all Optional. Include built-in skills in the listing.
Examples
# List user skills only
/list

# Include built-in skills
/list all

/read

/read Skill Management
Synopsis
/read <skill-name>
Description

Reads and displays the full content of a skill definition file. Shows the Markdown source with all sections.

Arguments
<skill-name> Required. The name of the skill to read.
Examples
/read equipment
/read user-validator

/write

/write Skill Management
Synopsis
/write <skill-name> [type]
Description

Creates a new skill or updates an existing one. If type is not specified for a new skill, you will be prompted to select one.

Arguments
<skill-name> Required. The name for the skill.
[type] Optional. Skill type: tskill, cskill, iskill, oskill, or mskill.
Examples
# Create a new table skill
/write inventory tskill

# Create an orchestrator skill
/write task-router oskill

/delete

/delete Skill Management
Synopsis
/delete <skill-name>
Description

Permanently removes a skill directory and all its contents. This action cannot be undone.

Arguments
<skill-name> Required. The name of the skill to delete.
Examples
/delete old-validator

/validate

/validate Quality Assurance
Synopsis
/validate <skill-name>
Description

Validates a skill definition against its schema requirements. Checks for required sections, proper formatting, and structural integrity.

Arguments
<skill-name> Required. The name of the skill to validate.
Examples
/validate equipment

/template

/template Skill Management
Synopsis
/template <type>
Description

Returns a blank template for the specified skill type. Use this to understand the required structure before creating a new skill.

Arguments
<type> Required. One of: tskill, cskill, iskill, oskill, mskill.
Examples
/template tskill
/template oskill

/generate

/generate Code Generation
Synopsis
/generate <skill-name>
Description

Generates executable JavaScript code from a skill definition. Creates a .generated.mjs file containing validators, enumerators, presenters, and other functions based on the skill type.

Arguments
<skill-name> Required. The skill to generate code for.
Generated Functions (tskill)
  • validator_<field>() - Field value validators
  • enumerator_<field>() - Enumeration options
  • presenter_<field>() - Display formatters
  • selectRecords() - Record filtering logic
  • prepareRecord() - Data transformation
  • validateRecord() - Full validation
Examples
/generate equipment

/test

/test Quality Assurance
Synopsis
/test [skill-name]
Description

Tests the generated code by importing and executing it. If no skill name is provided, displays an interactive picker to select a skill.

Arguments
[skill-name] Optional. The skill to test. Shows picker if omitted.
Examples
/test equipment
/test  # Shows interactive picker

/refine

/refine Code Generation
Synopsis
/refine <skill-name>
Description

Iteratively improves a skill through an automated edit-generate-test-evaluate loop. Continues until all tests pass or maximum iterations (5) is reached.

Refinement Loop
  1. Read current skill definition
  2. Validate structure
  3. Generate code
  4. Test generated code
  5. Evaluate against requirements
  6. Fix problematic sections
  7. Repeat until success
Examples
/refine equipment

/exec

/exec Execution
Synopsis
/exec <skill-name> [input]
Description

Executes any skill directly with optional input. Useful for testing skill behavior or running one-off operations.

Arguments
<skill-name> Required. The skill to execute.
[input] Optional. Input to pass to the skill.
Examples
/exec list-skills
/exec validate-skill equipment

/specs

/specs Skill Management
Synopsis
/specs <skill-name>
/specs-write <skill-name> [content]
Description

Read or write a skill's specification file (.specs.md). Specs files define constraints and requirements that are included in code generation context.

Examples
# Read specifications
/specs equipment

# Write specifications
/specs-write equipment

Skill Types

Skills are defined in Markdown files with structured sections. Each type serves a different purpose in the agent system.

tskill

.tskill.md

Database table entities with validators, enumerators, and presenters. Generates complete CRUD operations.

cskill

.cskill.md

Code skills where LLM generates implementation on-the-fly. Wrapper-only code generation.

iskill

.iskill.md

Interactive conversations with multi-step input collection. Generates action functions.

oskill

.oskill.md

Orchestrators that route requests to other skills. Generates routing logic.

mskill

.mskill.md

MCP (Model Context Protocol) tool integrations. Optional code generation.

tskill (Table Skills)

Table skills define database entities with comprehensive validation and presentation logic.

Required Sections

  • Summary - Brief description of the entity
  • Fields - Schema definition with types and constraints
  • Validators - Field validation rules
  • Enumerators - Allowed values for enumerated fields
  • Presenters - Display formatting rules

Example Structure

# equipment

## Summary
Manages laboratory equipment inventory and tracking.

## Fields
- equipment_id: string (primary key)
- name: string (required)
- status: enum [Available, In Use, Maintenance]
- area_id: reference (areas)
- last_calibration: date

## Validators
- equipment_id: Must match pattern EQP-XXXX
- name: Non-empty, max 100 characters

## Enumerators
- status: Available, In Use, Under Maintenance, Retired

## Presenters
- last_calibration: Format as "MMM DD, YYYY"

cskill (Code Skills)

Code skills allow the LLM to generate implementation logic dynamically based on the prompt and context.

Required Sections

  • Summary - What the skill does
  • Prompt - Instructions for the LLM
  • Arguments - Expected inputs

Example Structure

# validate-email

## Summary
Validates email addresses and extracts domain information.

## Prompt
Validate the provided email address. Check format, domain
existence, and return structured validation results.

## Arguments
- email: string - The email address to validate

iskill (Interactive Skills)

Interactive skills manage multi-turn conversations to collect information from users.

Required Sections

  • Summary - Conversation purpose
  • Instructions - How to guide the conversation
  • Input-Fields - Information to collect
  • Completion-Action - What happens when complete

oskill (Orchestrator Skills)

Orchestrators route user requests to appropriate skills based on intent analysis.

Required Sections

  • Summary - Orchestrator purpose
  • Instructions - Routing logic guidance
  • Allowed-Skills - List of skills this orchestrator can invoke

Example Structure

# task-router

## Summary
Routes task management requests to appropriate handlers.

## Instructions
Analyze user intent and route to the appropriate skill.
For creation requests, use create-task.
For queries, use list-tasks or search-tasks.

## Allowed-Skills
- create-task
- list-tasks
- search-tasks
- update-task
- delete-task

mskill (MCP Skills)

MCP skills integrate with external tools via the Model Context Protocol.

Required Sections

  • Summary - Tool description
  • MCP-Server - Server configuration
  • Tools - Available tool definitions

Specification Files (.specs.md)

Specification files are optional Markdown documents that provide additional context, constraints, and requirements for skills. They significantly improve code generation quality by giving the LLM detailed instructions.

Purpose

  • Guide Code Generation - Provide detailed requirements for generated code
  • Define Constraints - Specify validation rules, formats, and business logic
  • Document Implementation - Keep technical requirements separate from skill definition
  • Improve Consistency - Ensure generated code follows project standards

File Location

Place the .specs.md file in the same directory as the skill definition:

skills/
└── equipment/
    ├── tskill.md              # Skill definition
    ├── tskill.generated.mjs   # Generated code
    └── .specs.md              # Specifications (optional)

Basic Structure

# Equipment Skill - Technical Specification

## Overview
Brief description of what this skill does and its purpose.

## Schema Definition

### Primary Key
| Field | Format | Description |
|-------|--------|-------------|
| equipment_id | EQP-#### | Auto-generated unique identifier |

### Core Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | String | Yes | Equipment name (2-100 chars) |
| status | Enum | Yes | Current equipment status |

## Validation Requirements
- equipment_id must match pattern EQP-#### (e.g., EQP-0001)
- name must be 2-100 characters
- status must be one of: Available, In Use, Faulty

## Code Generation Prompt
Generate JavaScript/ESM code for the equipment database table skill.
[Detailed instructions for the LLM...]

Key Sections

Section Purpose
## Overview High-level description of the skill's purpose
## Schema Definition Detailed field definitions with types, formats, constraints
## Validation Requirements Specific validation rules and error messages
## Code Generation Prompt Custom prompt template for code generation (most important!)
## Required Exports List of functions that must be exported

Custom Code Generation Prompt

The most powerful feature of specs files is the ## Code Generation Prompt section. When present, this section replaces the default prompt sent to the LLM:

## Code Generation Prompt

Generate JavaScript/ESM code for the CoralFlow Equipment database table skill.

### Skill Info
- Skill Name: {{skillName}}
- Entity: equipment
- Primary Key Field: equipment_id
- Primary Key Format: EQP-#### (e.g., EQP-0001)

### Required Function Signatures

#### generatePKValues(record, existingRecords)
- Auto-generate equipment_id if not provided
- Find highest existing number, increment by 1
- Return: { equipment_id: "EQP-0001" }

#### validator_name(value, record)
- Check length: 2-100 characters
- Return: JSON.stringify({ field, error, value }) or empty string

### Code Style Requirements
- Use arrow functions for simple operations
- All validators return JSON string on error, empty string on success
- Include JSDoc comments
- Export all functions individually AND as default object
Template Variables

Use {{skillName}}, {{entityName}}, {{content}}, and {{sections}} in your prompts. These are automatically replaced with actual values during code generation.

How Specs Are Used

  1. When /generate is called, the system checks for .specs.md
  2. If found, specs content is loaded and passed to the prompt builder
  3. If specs contains ## Code Generation Prompt, it's used as the LLM prompt
  4. Otherwise, specs are appended to the default prompt as context
  5. The LLM generates code following the specifications

Commands

# Read existing specifications
/specs equipment

# Create or update specifications
/specs-write equipment

Code Generation Deep Dive

Understanding how code is generated from skill definitions helps you write better skills and troubleshoot issues.

Generation Pipeline

Code Generation Flow Pipeline
1. Trigger: /generate equipment
   ↓
2. Discover: Find equipment/tskill.md
   ↓
3. Check: Is regeneration needed?
   • Compare timestamps: tskill.md vs tskill.generated.mjs
   • Also check .specs.md timestamp
   ↓
4. Parse: Extract sections from Markdown
   • ## Table Purpose → sections['Table Purpose']
   • ## Fields → sections['Fields']
   ↓
5. Load Specs: Read .specs.md (if exists)
   ↓
6. Build Prompt: Select prompt builder by skill type
   • tskill → buildCodeGenPrompt()
   • iskill → buildIskillCodeGenPrompt()
   • oskill → buildOskillCodeGenPrompt()
   ↓
7. Execute LLM: Send prompt with mode='deep'
   ↓
8. Clean: Remove markdown code blocks from response
   ↓
9. Write: Save to tskill.generated.mjs
   ↓
10. Test: Auto-run tests if .tests.mjs exists

Generated Code Structure (tskill)

For table skills, the generated .mjs file contains these function types:

Validators

Validate individual field values. Return error JSON or empty string:

// validator_fieldName(value, record) → error string or ""
export function validator_equipment_id(value, record) {
    const regex = /^EQP-\d{4}$/;

    if (!value) {
        return JSON.stringify({
            field: "equipment_id",
            error: "Field is required",
            value
        });
    }

    if (!regex.test(value)) {
        return JSON.stringify({
            field: "equipment_id",
            error: "Must match format EQP-####",
            value
        });
    }

    return "";  // Valid
}

Enumerators

Return arrays of allowed values for enum fields:

// enumerator_fieldName(currentRecord) → string[]
export function enumerator_status(currentRecord) {
    return ["Available", "Allocated", "In Use", "Faulty", "Retired"];
}

export function enumerator_equipment_type(currentRecord) {
    return ["plant", "tool", "vehicle", "miscellaneous"];
}

Presenters

Format values for display:

// presenter_fieldName(value, record) → formatted string
export function presenter_verified_on(value, record) {
    if (!value) return "Not verified";

    const date = new Date(value);
    return date.toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'short',
        day: 'numeric'
    });
}

export function presenter_job_id(value, record) {
    if (!value || !record?.job) return "Not assigned";
    return `${record.job.name} (${record.job.client})`;
}

Resolvers

Convert human-friendly input to database format:

// resolver_fieldName(humanValue, record, context) → dbValue
export async function resolver_verified_on(humanValue, record) {
    if (!humanValue) return null;

    const input = humanValue.trim().toLowerCase();

    // Handle natural language dates
    if (input === "today") {
        return new Date().toISOString().split('T')[0];
    }
    if (input === "yesterday") {
        const d = new Date();
        d.setDate(d.getDate() - 1);
        return d.toISOString().split('T')[0];
    }

    // Parse standard date formats
    const date = new Date(humanValue);
    if (!isNaN(date.getTime())) {
        return date.toISOString().split('T')[0];
    }

    return null;
}

Record Operations

// Prepare record before database insert
export async function prepareRecord(record, context) {
    const prepared = { ...record };

    // Apply resolvers to transform human input
    if (prepared.verified_on !== undefined) {
        prepared.verified_on = await resolver_verified_on(
            prepared.verified_on, record
        );
    }

    return prepared;
}

// Validate entire record
export async function validateRecord(record) {
    const errors = [];

    const idError = validator_equipment_id(record.equipment_id, record);
    if (idError) errors.push(JSON.parse(idError));

    const nameError = validator_name(record.name, record);
    if (nameError) errors.push(JSON.parse(nameError));

    return {
        isValid: errors.length === 0,
        errors
    };
}

// Auto-generate primary key values
export function generatePKValues(record, existingRecords = []) {
    let maxNum = 0;
    for (const r of existingRecords) {
        const match = (r.equipment_id || '').match(/EQP-(\d+)/);
        if (match) maxNum = Math.max(maxNum, parseInt(match[1], 10));
    }
    return {
        equipment_id: 'EQP-' + String(maxNum + 1).padStart(4, '0')
    };
}

LLM Execution Options

Option Value Description
mode 'deep' Use more capable model for complex code generation
responseShape 'code' Expect raw code output (no JSON wrapper)
Regeneration Check

Code is only regenerated when source files are newer than the output. To force regeneration, either touch the source files or delete the .generated.mjs file.

Improving LLM Prompts

The quality of generated code depends heavily on the prompts sent to the LLM. Here's how to optimize them.

Prompt Sources (Priority Order)

  1. Custom Prompt in .specs.md - If ## Code Generation Prompt section exists, it's used directly
  2. Generic Prompt + Specs Context - Default prompt enhanced with specs content
  3. Generic Prompt Only - Fallback when no specs file exists

Writing Effective Specs

1. Be Specific About Formats

## Field Formats

| Field | Format | Example | Validation |
|-------|--------|---------|------------|
| equipment_id | EQP-#### | EQP-0001 | Regex: ^EQP-\d{4}$ |
| phone | E.164 | +1234567890 | Must start with + |
| email | RFC 5322 | user@example.com | Standard email regex |

2. Provide Function Signatures

## Required Function Signatures

### validator_equipment_id(value, record)
- Input: value (string), record (object)
- Output: JSON string with {field, error, value} OR empty string ""
- Must check: non-empty, matches EQP-#### format
- Error message: "Equipment ID must match format EQP-####"

3. Include Example Code

## Code Examples

### Validator Example
```javascript
export function validator_name(value, record) {
    if (!value || value.length < 2) {
        return JSON.stringify({
            field: "name",
            error: "Name must be at least 2 characters",
            value
        });
    }
    return "";
}
```

4. Specify Error Handling

## Error Handling Requirements

- All validators must handle null/undefined gracefully
- Return empty string "" for valid values, never null
- Error JSON must include: field, error, value
- Resolvers return null for unparseable input (don't throw)
- prepareRecord must preserve unknown fields (spread operator)

5. Define Code Style

## Code Style Requirements

- Use ES modules (export/import, not require)
- Use arrow functions for simple operations
- Use async/await for any potentially async operations
- Include JSDoc comments for all exported functions
- No console.log statements in production code
- Export functions individually AND as default object

Template Variables

Use these placeholders in your custom prompts:

Variable Description Example Value
{{skillName}} Name of the skill equipment
{{entityName}} Entity name (derived from skill) equipment
{{content}} Full skill definition markdown # Equipment Skill...
{{sections}} Parsed sections as JSON {"Fields": "...", "Validators": "..."}

Complete Specs Example

# Product Skill - Technical Specification

## Overview
Product skill manages inventory items with SKU tracking,
pricing, and category classification.

## Schema
| Field | Type | Required | Format |
|-------|------|----------|--------|
| product_id | String | Yes | PRD-#### |
| name | String | Yes | 2-100 chars |
| price | Number | Yes | >= 0, 2 decimals |
| category | Enum | Yes | See enumerator |

## Validation Rules
1. product_id: Auto-generated, format PRD-0001
2. name: Required, 2-100 characters, no special chars
3. price: Required, non-negative, max 2 decimal places
4. category: Must be from allowed list

## Code Generation Prompt

Generate ESM code for product database table skill.

Skill: {{skillName}}
Entity: product

### Required Exports
- generatePKValues(record, existingRecords)
- validator_product_id(value, record)
- validator_name(value, record)
- validator_price(value, record)
- enumerator_category(record)
- presenter_price(value, record)
- prepareRecord(record, context)
- validateRecord(record)

### Validator Return Format
- Valid: return ""
- Invalid: return JSON.stringify({ field, error, value })

### Price Presenter
Format as currency: "$1,234.56"

### Category Values
Electronics, Clothing, Food, Tools, Other

Generate clean ESM code with JSDoc comments.
Iterative Improvement

Use /refine skill-name to automatically improve code generation. The refiner reads test failures and updates the skill definition until tests pass.

Debugging Generation Issues

# Enable verbose mode to see prompts
achilles-cli --verbose

# Enable debug mode to see full JSON responses
achilles-cli --debug

# Test generated code
/test equipment

# Run specific test file
/run-tests equipment

Configuration

CLI Options

Option Description
-d, --dir <path> Working directory with skills
-v, --verbose Enable verbose logging
--debug Enable debug mode (shows JSON output)
--fast Use fast LLM mode (cheaper, quicker)
--deep Use deep LLM mode (default, more capable)
--no-markdown Disable markdown rendering

Environment Variables

At least one API key is required. You can configure multiple providers.

Variable Description
OPENAI_API_KEY API key for OpenAI (GPT-4o, GPT-4o-mini)
ANTHROPIC_API_KEY API key for Anthropic (Claude Sonnet, Claude Opus)
GEMINI_API_KEY API key for Google (Gemini 2.5 Pro, Gemini 2.5 Flash)
OPENROUTER_API_KEY API key for OpenRouter (multiple model access)
HUGGINGFACE_API_KEY API key for Hugging Face models
ACHILLES_ORCHESTRATOR_MODE Default LLM mode: 'fast' or 'deep'

Directory Structure

my-project/
├── skills/           # User-defined skills
│   ├── my-skill/
│   │   ├── my-skill.tskill.md
│   │   ├── my-skill.tskill.generated.mjs
│   │   ├── my-skill.specs.md
│   │   └── my-skill.tests.mjs
│   └── another-skill/
│       └── ...
└── .achilles-cli-history     # Command history

Common Workflows

Creating a New Validator

# 1. Get the template
/template tskill

# 2. Create the skill
/write product-validator tskill

# 3. Validate structure
/validate product-validator

# 4. Generate code
/generate product-validator

# 5. Test the generated code
/test product-validator

Iterative Improvement

# Automatic refinement loop
/refine product-validator

# Or manually update a section
/update product-validator validators

Building an Orchestrator

# 1. Create the orchestrator
/write inventory-manager oskill

# 2. Define allowed skills in the file
/read inventory-manager

# 3. Test routing behavior
/exec inventory-manager "show all products"

Architecture

System Overview

┌─────────────────────────────────────────────────────────────┐
│                      Entry Point                             │
│                      (index.mjs)                             │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                     REPLSession                              │
│   ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐  │
│   │InteractivePrompt│ │  QuickCommands  │ │     NLP      │  │
│   │  (input/history)│ │(instant actions)│ │ (LLM routing)│  │
│   └─────────────────┘ └─────────────────┘ └──────────────┘  │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                  SlashCommandHandler                         │
│              (deterministic command routing)                 │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                 RecursiveSkilledAgent                        │
│   ┌─────────────────┐        ┌─────────────────────────┐    │
│   │  Built-in Skills │        │     User Skills         │    │
│   │  (src/.Achilles) │        │  (skills/)     │    │
│   └─────────────────┘        └─────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘

Repository Structure

achilles-cli/           # Ploinky repository
├── CLAUDE.md               # Architecture documentation
├── docs/                   # This documentation
├── tests/                  # Test files
└── achilles-cli/          # Ploinky agent
    ├── manifest.json       # Agent manifest
    ├── scripts/            # Install scripts
    ├── src/                # Source code
    │   ├── index.mjs       # Entry point
    │   └── skills/ # Built-in skills
    └── bin/                # CLI binaries

Two-Layer Skill Discovery

  1. Built-in Skills - Bundled with CLI in achilles-cli/src/skills/
  2. User Skills - Project-specific in skills/

User skills can override built-in skills of the same name.

Dependencies

  • achilles-agent-lib - Core agent execution framework
  • RecursiveSkilledAgent - Skill discovery and execution
  • LLM Providers - OpenAI, Anthropic, Google, OpenRouter, Hugging Face
Design Philosophy

Skills are defined in Markdown for human readability, LLM-native processing, and version control friendliness. Code generation is reserved for complex logic like validators and presenters.