> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simplefunctions.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills

> Agent skills — built-in cognitive guardrails plus user-defined slash commands stored on SimpleFunctions and runnable from any agent.

A **skill** is a packaged prompt + metadata that any SimpleFunctions agent can invoke as a slash command. SimpleFunctions ships \~19 built-in skills (cognitive guardrails like `/precheck`, `/discipline`, plus 16 topical context packs), and authenticated users can author and publish their own.

There are two layers:

| Layer       | Source                                                  | Auth               | Purpose                                                                       |
| ----------- | ------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------------- |
| Built-in    | `GET /api/skills`                                       | none               | Cognitive guardrails and topical context packs maintained by SimpleFunctions. |
| User skills | `/api/skill*` (CRUD) and `/api/public/skill*` (catalog) | required for write | Custom skills the user authored. Forkable. Optionally publishable.            |

## Built-in skills

The CLI ships built-in skills directly. Inside `sf agent`, type `/<trigger>` to run one. List them via the public API:

```bash theme={null}
curl https://simplefunctions.dev/api/skills
```

```json theme={null}
{
  "count": 19,
  "description": "Agent cognitive guardrails and workflows for prediction markets.",
  "install": "npm install -g @spfunctions/cli",
  "usage": "Inside sf agent, type /<skill-name> to run a skill.",
  "skills": [
    {
      "name": "precheck",
      "trigger": "/precheck",
      "description": "Pre-trade adversarial check — argue against the trade before executing it.",
      "author": "simplefunctions",
      "version": "1.0.0",
      "category": "risk-management",
      "tags": ["trading", "pre-trade", "adversarial", "bias-check"],
      "toolsUsed": ["inspect_book", "get_context", "what_if", "scan_markets"],
      "estimatedTime": "1-2 minutes",
      "auto": "before_trade"
    }
  ]
}
```

This endpoint is **public, cached 1h**. It is the single source of truth for what built-in skills the running CLI exposes.

## User skills — full schema

A user skill row contains:

| Field                    | Type              | Notes                                                           |
| ------------------------ | ----------------- | --------------------------------------------------------------- |
| `id`                     | uuid              | Primary key.                                                    |
| `userId`                 | uuid              | Owner.                                                          |
| `name`                   | string            | Display name.                                                   |
| `trigger`                | string            | Slash command (e.g. `/my-screener`). Must be unique per user.   |
| `description`            | string            | One-line description.                                           |
| `prompt`                 | string            | The instructions the agent runs.                                |
| `category`               | string            | `custom` (default), `trading`, `research`, `monitoring`.        |
| `tags`                   | string\[]         | Discovery tags.                                                 |
| `toolsUsed`              | string\[]         | SimpleFunctions tools this skill calls (informational).         |
| `estimatedTime`          | string \| null    | E.g. "1-2 minutes".                                             |
| `auto`                   | string \| null    | Auto-trigger condition (e.g. `before_trade`).                   |
| `isPublic`               | boolean           | Default `false`.                                                |
| `publicSlug`             | string \| null    | Set when published. 3–60 chars, lowercase, numbers, hyphens.    |
| `publishedAt`            | timestamp \| null | Time of first publish.                                          |
| `forkedFromId`           | uuid \| null      | Parent skill if this row is a fork.                             |
| `forkCount`              | number            | Times this skill has been forked (only meaningful when public). |
| `runCount`               | number            | Times this skill has been retrieved via `run_skill`.            |
| `version`                | string            | User-managed semver. Defaults to `1.0.0`.                       |
| `createdAt`, `updatedAt` | timestamp         | Server-set.                                                     |

## Authentication

Every endpoint below except `GET /api/public/skills*` and `GET /api/skills` requires `Authorization: Bearer sf_live_xxx`. Mutating endpoints additionally enforce ownership: only the row's `userId` can update, delete, fork (their own), or publish it.

## CRUD endpoints

### Create a skill

```http theme={null}
POST /api/skill
```

```bash theme={null}
curl -X POST "https://simplefunctions.dev/api/skill" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Fed cut adversarial check",
    "trigger": "/fed-precheck",
    "description": "Argues against any FOMC-rate-cut market before recommending entry.",
    "prompt": "You are about to recommend a trade on a Fed-rate-cut market...",
    "category": "trading",
    "tags": ["fed", "rates", "precheck"],
    "toolsUsed": ["inspect_ticker", "what_if", "get_context"],
    "estimatedTime": "1-2 minutes"
  }'
```

Required body fields: `name`, `trigger`, `description`, `prompt`. Returns `201` with the new row.

| Status | Body                                                               | Cause                          |
| ------ | ------------------------------------------------------------------ | ------------------------------ |
| `400`  | `{ error: "name, trigger, description, and prompt are required" }` | Missing required field.        |
| `401`  | `{ error: "unauthorized" }`                                        | Bearer key missing or invalid. |
| `500`  | `{ error: "Internal server error" }`                               | DB write failed.               |

### List your skills

```http theme={null}
GET /api/skill
```

Returns built-in skills + the caller's custom skills:

```json theme={null}
{
  "skills": [
    { "name": "precheck", "trigger": "/precheck", "isBuiltIn": true, "...": "..." },
    { "id": "sk_...", "name": "Fed cut adversarial check", "isBuiltIn": false, "...": "..." }
  ],
  "count": 20
}
```

### Get one skill

```http theme={null}
GET /api/skill/{id}
```

Returns the full skill row. `404` if not found or not owned by the caller.

### Update a skill

```http theme={null}
PUT /api/skill/{id}
```

Partial update. Send only the fields you want to change. Mutable fields: `name`, `trigger`, `description`, `prompt`, `category`, `tags`, `toolsUsed`, `estimatedTime`, `auto`, `version`.

```bash theme={null}
curl -X PUT "https://simplefunctions.dev/api/skill/$SKILL_ID" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "version": "1.1.0", "description": "Updated copy" }'
```

`404` when the row doesn't exist or isn't owned by the caller. Server stamps `updatedAt`.

### Delete a skill

```http theme={null}
DELETE /api/skill/{id}
```

Returns `{ deleted: true, id }`. Hard delete. `404` if not found.

## Fork a public skill

```http theme={null}
POST /api/skill/{id}/fork
```

Forks a public skill into the caller's collection. The fork copies `name` (with " (fork)" suffix), `trigger`, `description`, `prompt`, `category`, `tags`, `toolsUsed`, `estimatedTime`, and sets `forkedFromId` to the original. `forkCount` on the original is atomically incremented.

```bash theme={null}
curl -X POST "https://simplefunctions.dev/api/skill/$ORIGINAL_ID/fork" \
  -H "Authorization: Bearer $SF_API_KEY"
```

Returns `201` with the new row. `404` if the source skill isn't public or doesn't exist.

## Publish / unpublish

```http theme={null}
POST   /api/skill/{id}/publish    # publish
DELETE /api/skill/{id}/publish    # unpublish
```

Publishing flips `isPublic = true` and pins a public slug:

```bash theme={null}
curl -X POST "https://simplefunctions.dev/api/skill/$SKILL_ID/publish" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "my-fed-precheck" }'
```

Slug rules: `^[a-z0-9-]{3,60}$`. Unique across all published skills.

| Status | Body                                                              | Cause                        |
| ------ | ----------------------------------------------------------------- | ---------------------------- |
| `400`  | `{ error: "slug is required" }`                                   | Body missing `slug`.         |
| `400`  | `{ error: "Slug: 3-60 chars, lowercase, numbers, hyphens only" }` | Slug regex failed.           |
| `404`  | `{ error: "Skill not found" }`                                    | Not owned by caller.         |
| `409`  | `{ error: "Slug already taken" }`                                 | Another skill owns the slug. |

Successful publish returns `{ published: true, slug, skill }`. The skill is then live at `simplefunctions.dev/skills/{slug}` and discoverable via `GET /api/public/skills`.

Unpublish flips `isPublic = false` and returns `{ unpublished: true }`. The slug is **kept** so future publishes can reuse it.

## Public catalog

```http theme={null}
GET /api/public/skills?category=&q=&sort=
GET /api/public/skill/{slug}
```

`/api/public/skills` returns up to 100 published skills, optionally filtered:

| Query      | Type               | Purpose                                                                          |
| ---------- | ------------------ | -------------------------------------------------------------------------------- |
| `category` | string             | Filter by category.                                                              |
| `q`        | string             | Substring match on `name` and `description`.                                     |
| `sort`     | `popular` \| `new` | `popular` ranks by `forkCount + runCount`; `new` (default) ranks by `createdAt`. |

`/api/public/skill/{slug}` returns the full row including `prompt` text. Both endpoints are no-auth, `Cache-Control: public, s-maxage=300`.

## Discovering skills from MCP

These tools are also available over MCP — see [MCP tools reference](/reference/mcp-tools):

* `create_skill`, `list_skills`, `run_skill`, `publish_skill`, `fork_skill` — authenticated.
* `browse_public_skills` — public.

`run_skill` returns the skill's `prompt` and metadata; **execution happens in the calling agent** (Claude Code, Cursor, `sf agent`, etc.) — the SimpleFunctions server does not run the prompt itself.

## See also

<CardGroup cols={2}>
  <Card title="MCP tools reference" href="/reference/mcp-tools">
    `create_skill`, `fork_skill`, `publish_skill`, full schemas.
  </Card>

  <Card title="Build agents" href="/guides/agents">
    How skills compose with the SimpleFunctions agent loop.
  </Card>

  <Card title="Agentic CLI" href="/cli/agentic-cli">
    Built-in skills are bundled here; `sf agent` recognizes their slash commands.
  </Card>

  <Card title="Browse public skills" href="https://simplefunctions.dev/skills">
    Live catalog on the website.
  </Card>
</CardGroup>
