Base Context can create skills. Ask it to build one for your use case.
Skills are self-contained capability packages that Base Context loads on demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
Base Context implements the Agent Skills standard, warning about violations but remaining lenient. It also supports Python-backed skills: a superset of markdown skills that install Python packages into the persistent Python kernel.
- Locations
- Built-in Skills
- How Skills Work
- Reusable Helpers Without Packaging
- Python-Backed Skills
- Creating Skills with Base Context
- Skill Commands
- Skill Structure
- Frontmatter
- Validation
- Example
- Skill Repositories
Security: Skills can instruct the model to perform any action and may include executable code the model invokes. Review skill content before use.
Base Context loads skills from:
- Global:
~/.base-context/skills/~/.agents/skills/
- Project:
.base-context/skills/.agents/skills/incwdand ancestor directories (up to git repo root, or filesystem root when not in a repo)
- Packages:
skills/directories orpi.skillsentries inpackage.json - Settings:
skillsarray with files or directories - CLI:
--skill <path>(repeatable, additive even with--no-skills) - Built-in:
skills/shipped with the @ponythewhite/base-context package (lowest precedence)
Discovery rules:
- In
~/.base-context/skills/and.base-context/skills/, direct root.mdfiles are discovered as individual skills - In all skill locations, directories containing
SKILL.mdare discovered recursively - In
~/.agents/skills/and project.agents/skills/, root.mdfiles are ignored
Disable discovery with --no-skills (explicit --skill paths still load).
Base Context ships with built-in skills that load by default:
skill-creator- teaches the agent to create new skills: markdown skill layout, frontmatter rules, placement and precedence, and the full Python-backed skill contract (package layout,run()convention, optional CLI, kernel venv behavior) with a working template inreferences/python-skills.md.websearch- a Python-backed Google search skill using the Serper API.
Built-in skills behave like any other skill but have the lowest precedence: a user, project, package, or --skill skill with the same name overrides the built-in one.
Setup: get a free API key at serper.dev, then run /login,
switch to MCP Connections using the displayed tab shortcuts, and choose
Serper (web search) to paste it. The key is stored alongside your other
credentials (in auth.json) and read by the skill on each call — no environment
variables required, and it works even if you add the key mid-session.
Optional overrides (environment variables):
export BASE_CONTEXT_WEBSEARCH_TIMEOUT=45
export BASE_CONTEXT_WEBSEARCH_NUM_RESULTS=5A SERPER_API_KEY in the environment, if set, takes precedence over the stored key.
Once loaded, the model can call it directly in the Python kernel by import name:
print(await websearch("latest Base Context release"))Until a key is configured, web search returns a clear message telling the agent
to walk you through /login.
Disable only the built-in websearch skill in settings:
{
"bundledSkills": {
"websearch": false
}
}To disable all built-in skills, set enableBuiltinSkills to false in settings.json (or toggle "Built-in skills" in /settings):
{
"enableBuiltinSkills": false
}--no-skills also excludes built-in skills. To disable a single built-in skill without a dedicated setting, force-exclude it in the global skills array (patterns resolve against the built-in skills directory):
{
"skills": ["-prime-intellect/SKILL.md"]
}To use skills from Claude Code or OpenAI Codex, add their directories to settings:
{
"skills": [
"~/.claude/skills",
"~/.codex/skills"
]
}For project-level Claude Code skills, add to .base-context/settings.json:
{
"skills": ["../.claude/skills"]
}- At startup, Base Context scans skill locations and extracts names, descriptions, type, and file locations
- The system prompt includes visible skills in XML format per the specification
- When a task matches, the agent selects the full instructions through the native route described below. Generic non-native requests keep the existing
ipythonfile-read path. Use/skill:nameto invoke a skill explicitly. - The agent follows the instructions, using relative paths to reference scripts and assets
This is progressive disclosure: only descriptions are always in context, full instructions load on-demand.
For native epochs, select an advertised skill with
prime_context using {"action":"skill","name":"..."}. The response gives its
captured body and canonical source reference. Use the returned ref and field with
action="read" for bounded recovery; do not reopen the mutable location to replace
a selected version. A committed epoch keeps that selected descriptor and instruction
body. After an existing context transition commits a new epoch, a later selection
can capture updated contents. The original captured body remains recoverable from
its source ref after rotation. A file edit alone does not replace an active version.
In native epoch mode, model-invocable skills are advertised only when the
configured tools permit the native selection/recovery route. A disabled, replaced,
or disallowed recovery tool is not enabled implicitly. Explicit /skill:name
commands remain available, including skills marked disable-model-invocation.
Generic non-native behavior is unchanged.
Skills with disable-model-invocation: true are hidden from the startup skill list. They can still be invoked explicitly with /skill:name.
For repeated multi-step work, start with an ordinary named Python function in
ipython. Keep one-off operations inline and prefer an existing project command
when it already does the work. Give changing paths, selectors, output paths and
options explicit parameters. Reuse the code, not its previous answer: read current
inputs on every call. Do not capture an open handle or hidden mutable REPL state.
After two useful occurrences across tasks, or an explicit request for reuse, save
the function in an editable .py file with a short project markdown skill. This
is a practical heuristic, not a repetition detector. A small helper needs no
pyproject.toml, package installation, manifest or promotion step. Use the standard
library and dependencies already available in the selected environment.
For example, save scripts/matching_lines.py in
.base-context/skills/matching-lines/:
from pathlib import Path
def matching_lines(path: str, needle: str, limit: int = 20) -> list[tuple[int, str]]:
"""Read a current UTF-8 file; return literal matches with one-based lines."""
if limit < 1:
raise ValueError("limit must be positive")
matches = []
with Path(path).open(encoding="utf-8") as source:
for line_number, line in enumerate(source, start=1):
if needle in line:
matches.append((line_number, line.rstrip("\r\n")))
if len(matches) == limit:
break
return matchesAdd the ordinary SKILL.md next to scripts/:
---
name: matching-lines
description: Read current UTF-8 files for repeated literal line lookups. Inputs are path, needle and limit; output is a list of one-based line numbers and text.
---
Load scripts/matching_lines.py afresh with runpy.run_path, then call
matching_lines(path, needle, limit=20). Resolve the script path against this
skill directory. No matches returns an empty list; ordinary errors propagate.Only the short skill description enters discovery. Load the instructions and code
when the active task needs them. For this standard-library helper, a fresh load
and call in ipython can be:
from runpy import run_path
matching_lines = run_path("/repo/.base-context/skills/matching-lines/scripts/matching_lines.py")["matching_lines"]
matches = matching_lines("/repo/current.txt", "needle", limit=20)After editing a loaded helper, execute its updated definition before calling it again, or load the saved script afresh as above. For project imports or commands, use the project's own environment instead of installing them into the kernel. Fresh execution of editable code does not replace the captured instruction body of an active native skill epoch.
Saving a helper does not schedule or authorize execution. Invocation still needs the normal model/tool decision or an explicit user workflow, under the existing permissions. Do not add an import manager, dependency snapshots or per-call setup.
For a useful comparison, include construction and failed attempts, then compare 1, 2 and 5 uses with the direct path. Record construction time/tokens, later model/tool calls and total sequence cost; report time and money separately. A first use is not free warmup. Keep the direct path when saving and finding the helper costs more than it saves.
A Python-backed skill uses the same SKILL.md metadata and invocation behavior as a markdown skill, but also provides a Python package for the Python kernel.
web-search/
├── SKILL.md
├── pyproject.toml
└── src/
└── web_search/
└── __init__.py
Detection rules:
SKILL.mdis still requiredpyproject.tomlmarks the skill as Python-backed- the import name is the skill name with hyphens converted to underscores
src/<import_name>/__init__.pymust exist
For web-search, Base Context exposes web_search in the Python REPL. If the module defines run(), the module is wrapped as an async callable:
await web_search("prime agent skills")
await web_search.run("prime agent skills")
help(web_search)Python skills are installed editable during normal kernel setup. An owned installation
uses its selected release-local runtime directory. Other installations default to
~/.base-context/runtime (under BASE_CONTEXT_HOME when configured).
BASE_CONTEXT_KERNEL_VENV selects a different venv. Normal skill synchronization
can update that environment; an epoch's selected instruction body is not an
immutable Python-package or filesystem snapshot.
If you set BASE_CONTEXT_KERNEL_PYTHON, Base Context does not install packages into
that environment. The Python must already have a current base-context-runtime
and the default runtime packages installed. Missing Python skill imports are
disabled with a warning and calling the skill raises a RuntimeError. This manual
override is outside the owned installation's default CLI/Python pairing.
A Python skill can expose a shell command by declaring a console script in pyproject.toml. The script name must exactly match the Python import name, including underscores:
[project]
name = "web-search"
version = "0.1.0"
dependencies = ["requests"]
[project.scripts]
web_search = "rlm.skill:cli"The rlm.skill:cli helper imports web_search.run, parses CLI arguments with tyro, awaits async results, and prints non-None return values.
async def run(query: str, limit: int = 5) -> str:
"""Search the web and return a concise summary."""
...The model can then call the skill from normal Python or from shell mode:
await web_search("prime agent")
!web_search "prime agent" --limit 3Base Context ships with a built-in skill-creator skill that teaches the agent both the Agent Skills format and the Python-backed package contract. You can ask for a skill in normal language:
Create a project Python-backed skill named release-audit in
.base-context/skills/release-audit. It should expose
await release_audit(repository, target_version), include concise SKILL.md
instructions, declare its dependencies, and verify the callable in a fresh
Base Context session.
To force the creation workflow explicitly, invoke the built-in skill command:
/skill:skill-creator Create a personal markdown skill for reviewing database migrations.
Tell the agent three things:
- Scope: use
.base-context/skills/<name>/for a project skill committed with the repository, or~/.base-context/skills/<name>/for a personal skill. - Kind: use a markdown skill with editable scripts for small reusable helpers. Ask for a Python-backed skill when an installed module and its package dependencies are needed.
- Contract: describe the intended Python call, inputs, output, dependencies, credentials, and verification behavior.
The agent should create SKILL.md in both cases. For a Python-backed skill it should also create pyproject.toml and src/<import_name>/__init__.py, expose a documented callable, and verify that the package imports in the kernel.
Use /reload to rediscover new or edited skill metadata. Start a fresh Base Context session after adding a Python-backed skill so kernel setup can install and import the package.
An installed Python-backed skill is a real package on disk that adds executable functionality to the kernel. A continual harness skill entry is a persisted description of a reusable Python call, including its reference and argument contract. /refine can create or update the latter after a repeated procedure emerges, but a description does not create executable code. Small helpers can use the editable script and markdown-skill path above; an installed package is optional.
Skills register as /skill:name commands:
/skill:brave-search # Load and execute the skill
/skill:pdf-tools extract # Load skill with argumentsArguments after the command are appended to the skill content as User: <args>.
Toggle skill commands via /settings in interactive mode or in settings.json:
{
"enableSkillCommands": true
}A skill is a directory with a SKILL.md file. Everything else is freeform.
my-skill/
├── SKILL.md # Required: frontmatter + instructions
├── scripts/ # Helper scripts
│ └── process.sh
├── references/ # Detailed docs loaded on-demand
│ └── api-reference.md
└── assets/
└── template.json
---
name: my-skill
description: What this skill does and when to use it. Be specific.
---
# My Skill
## Setup
Run once before first use:
```bash
cd /path/to/skill && npm install
```
## Usage
```bash
./scripts/process.sh <input>
```Use relative paths from the skill directory:
See [the reference guide](references/REFERENCE.md) for details.Per the Agent Skills specification:
| Field | Required | Description |
|---|---|---|
name |
Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Must match parent directory. |
description |
Yes | Max 1024 chars. What the skill does and when to use it. |
license |
No | License name or reference to bundled file. |
compatibility |
No | Max 500 chars. Environment requirements. |
metadata |
No | Arbitrary key-value mapping. |
allowed-tools |
No | Space-delimited list of pre-approved tools (experimental). |
disable-model-invocation |
No | When true, skill is hidden from system prompt. Users must use /skill:name. |
- 1-64 characters
- Lowercase letters, numbers, hyphens only
- No leading/trailing hyphens
- No consecutive hyphens
- Must match parent directory name
Valid: pdf-processing, data-analysis, code-review
Invalid: PDF-Processing, -pdf, pdf--processing
The description determines when the agent loads the skill. Be specific.
Good:
description: Extracts text and tables from PDF files, fills PDF forms, and merges multiple PDFs. Use when working with PDF documents.Poor:
description: Helps with PDFs.Base Context validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
- Name doesn't match parent directory
- Name exceeds 64 characters or contains invalid characters
- Name starts/ends with hyphen or has consecutive hyphens
- Description exceeds 1024 characters
Unknown frontmatter fields are ignored.
Exception: Skills with missing description are not loaded.
Name collisions (same name from different locations) warn and keep the first skill found.
brave-search/
├── SKILL.md
├── search.js
└── content.js
SKILL.md:
---
name: brave-search
description: Web search and content extraction via Brave Search API. Use for searching documentation, facts, or any web content.
---
# Brave Search
## Setup
```bash
cd /path/to/brave-search && npm install
```
## Search
```bash
./search.js "query" # Basic search
./search.js "query" --content # Include page content
```
## Extract Page Content
```bash
./content.js https://example.com
```- Anthropic Skills - Document processing (docx, pdf, pptx, xlsx), web development
- Pi Skills - Web search, browser automation, Google APIs, transcription