Skip to content

Skills

Skills are modular extensions to the AI agent. A skill can provide:

  • Domain knowledge: instructions the agent receives for a task
  • Runnable scripts — tools the agent can call during a task (shell scripts, Python scripts, TypeScript, executables)
  • Reference files — documentation the agent can query mid-task

Skills allow you to give the agent specialised expertise for specific frameworks, internal APIs, company conventions, or complex workflows without modifying Tarsk itself.

Tarsk lists each skill’s name, description, and when-to-use text in the system prompt under an # Available Skills section before the agent processes your request. Full SKILL.md instructions load only when you invoke the skill explicitly with /skill-name or //skill-name, or when the thread’s enabledSkills list enables it. In every other case, the agent calls the read_skill tool to load the skill’s full instructions on demand when they look relevant to the task.

Set disable-model-invocation: true in the skill frontmatter to keep a skill out of the catalog. Invoke such skills manually with /skill-name (see below).

A skill is a directory containing a SKILL.md file. The minimum structure is:

my-skill/
SKILL.md

Write YAML frontmatter followed by the skill’s instructions in SKILL.md. Tarsk includes these instructions with your message when you invoke or enable the skill:

---
name: my-skill
description: Provides guidance for working with internal payments API.
license: MIT
compatibility: Node.js 18+, Python 3.9+
---
## Payments API
Always use `PaymentService` class from `src/services/payment.ts`.
Never call Stripe API directly — use abstraction layer.
...
FieldRequiredDescription
nameYesDisplay name for skill (must match directory name, 1-64 chars, lowercase alphanumeric, hyphens only)
descriptionYesShown in the Available Skills catalog; helps the agent decide when to load the skill (1-1024 chars)
licenseNoLicense identifier (e.g. MIT)
compatibilityNoSystem requirements or dependencies
allowed-toolsNoFilter deferred tools and control shell interpolation (see Tool Allowlists)
when_to_useNoShown to the agent as guidance for when the skill applies
disable-model-invocationNoWhen true, the skill stays out of the Available Skills catalog; invoke it manually with /skill-name (see below)

Tarsk combines non-empty allowed-tools lists from skills invoked with /skill-name or //skill-name and from the thread’s enabledSkills for the current turn. It uses a union: if one skill lists browser and another lists find_images, the agent can use both. Tarsk ignores absent or empty lists; if no non-empty list remains, it applies no skill-based tool filter. An entry of * or all in any of these skills removes the skill-based tool filter.

The Available Skills catalog does not contribute to this union. Calling read_skill loads and preprocesses instructions without changing the turn’s tool allowlist.

Tarsk applies this filter to deferred tools, including optional and MCP tools behind tool_search. It leaves eager tools, such as read, write, edit, and bash, outside the filter. Optional or MCP tools configured for eager loading also bypass it. Project tool settings and mode restrictions still apply; use allowed-tools to select deferred tools, not to enforce read-only access.

Tarsk keeps the management tools ask_user, todo, tasks, tool_search, and read_skill in the resolved allowlist. A Bash or Bash(pattern) entry also includes execute_skill_script; a Read entry includes read_skill_reference. These entries do not enable tools that project settings or the current mode exclude.

For shell tool approvals, Tarsk adds the current turn’s Bash(pattern) entries to the project’s allowed command patterns. A matching bash command or script launch can run without an approval prompt. Bare Bash does not grant blanket approval for these tool calls. See Script execution and permissions for script checks and Shell command security for template commands.

When a skill is activated, its instructions are preprocessed before injection. You can embed dynamic content:

SyntaxDescription
!`command`Run a shell command and substitute the output inline
```! ... ```Run a multi-line shell command block
!`tarsk:models`Inject a list of enabled models with pricing and coding intelligence
$ARGUMENTS, $0, $nameSubstitute skill invocation arguments
${TARSK_SKILL_DIR}Absolute path to the skill directory

Tarsk checks each template command against the containing skill’s own allowed-tools, including when the agent loads it with read_skill. It does not use the combined tool allowlist for this check:

  • Bash(pattern) permits commands that match the pattern. For example, Bash(git *) matches git diff HEAD.
  • Bare Bash permits any shell command in that skill’s template.
  • Without a matching Bash entry, Tarsk substitutes an error message for the command. Tool entries such as * or all do not grant shell interpolation permission.

Pattern matching does not validate shell syntax or constrain each command in a pipeline or command chain. A trailing * matches a token prefix, so Bash(git *) can also match text that starts with git and contains shell operators. Tarsk substitutes invocation arguments before this check without shell escaping.

Template commands run through the host shell without Tarsk’s shell-approval gate or Seatbelt sandbox wrapper. Project shell permissions do not govern this path, and the script tool’s timeout does not apply. Review a skill’s template commands and argument handling before invoking it or making it available to the agent.

!`tarsk:models` expands to enabled models sorted cheapest-first, one per line:

- anthropic/claude-haiku-4.5 at $0.80 in, $4.00 out, intelligence at 35
- google/gemini-2.0-flash at $0.10 in, $0.40 out, intelligence at 28

Prices are USD per million tokens (rounded to the cent). Intelligence is the model’s coding index. This builtin does not require Bash in allowed-tools.

---
name: cheap-subagent
description: Delegate simple tasks to a cheap subagent
allowed-tools: Bash agent
---
Available models (cheapest first):
!`tarsk:models`
For simple subtasks, use the agent tool with model and provider from the cheapest entry above.
my-skill/
SKILL.md
scripts/ ← runnable tools exposed to agent
generate.sh
validate.py
scaffold.ts
references/ ← documentation agent can read on demand
api-spec.md
schema.json
assets/ ← static files, images, data
templates/
output.json

scripts/: The agent runs files here through execute_skill_script, with optional arguments. Supported types:

  • .sh, .bash → bash
  • .py → python3
  • .js → node
  • .ts → bun run
  • Other extensions → Direct execution if executable

references/ — Files agent can read via read_skill_reference. Useful for large specifications or schemas you don’t want injected into every prompt automatically.

assets/ — Static files the skill can reference, such as templates, configuration files, or data files.

The agent calls execute_skill_script to run a file from a skill’s scripts/ directory. Tarsk checks the interpreter, script path, and arguments as a launch command through the shell-permission gate when a project gate exists. With shell approval enabled, an unmatched launch requires your approval. This check covers the launch command, not each command inside the script; the executor does not recheck the script’s own skill-specific Bash(pattern) entries.

With Seatbelt enabled on macOS, Tarsk wraps the script process in the sandbox and adds the skill directory to its readable paths. The tool uses a 30-second timeout by default and accepts a timeout override. Template shell interpolation uses a separate execution path, as described under Shell command security.

Tarsk loads skills from three directories plus its bundled skills:

LocationScope
~/.agents/skills/Global, available to all projects
<projectPath>/.agents/skills/Project, only available within that project
<threadPath>/.agents/skills/Thread, only available within that thread

Project skills override global skills with the same name, and thread skills override both. Tarsk also ships app-bundled skills that are available everywhere; a project or global skill with the same name overrides the bundled one.

Open Settings → Plugins → Skills to browse and install community skills with one click. Installed skills are saved to the project’s .agents/skills/ directory.

  1. Create a directory in ~/.agents/skills/ (global) or <threadPath>/.agents/skills/ (project-level):
    Terminal window
    mkdir -p ~/.agents/skills/my-skill
  2. Create SKILL.md with the frontmatter and instructions.
  3. Optionally add scripts/ and references/ subdirectories.
  4. Start a new conversation — the skill is available immediately.
---
name: react-query-conventions
description: Conventions for using React Query and TanStack Query in this project.
---
## Query Keys
Always define query keys as constants in `src/query-keys.ts`.
Never inline query key strings.
## Mutations
Use `useMutation` hook from `@tanstack/react-query`:
```typescript
const createUser = useMutation({
mutationFn: (userData: CreateUserInput) => api.post("/users", userData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: queryKeys.users });
toast.success("User created successfully");
},
onError: (error) => {
toast.error(`Failed to create user: ${error.message}`);
},
});
```
Always invalidate related queries in `onSuccess`.
### Queries
Use `useQuery` with proper error handling:
```typescript
const { data: users, isLoading, error } = useQuery({
queryKey: queryKeys.users,
queryFn: () => api.get('/users'),
staleTime: 5 * 60 * 1000, // 5 minutes
retry: 3
});
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorMessage error={error} />;
return <UserList users={users} />;
```

Invoke /react-query-conventions to load this skill’s instructions. For other prompts, the agent can choose to load it with read_skill based on its description.

File: ~/.agents/skills/pdf-processing/scripts/extract-text.py

#!/usr/bin/env python3
import sys
import json
import PyPDF2
def main():
if len(sys.argv) < 2:
print(json.dumps({"error": "No PDF path provided"}), file=sys.stderr)
sys.exit(1)
pdf_path = sys.argv[1]
try:
with open(pdf_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
text = ""
for page in reader.pages:
text += page.extract_text()
print(json.dumps({
"success": True,
"text": text,
"pages": len(reader.pages)
}))
except Exception as e:
print(json.dumps({"error": str(e)}), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

Make it executable:

Terminal window
chmod +x ~/.agents/skills/pdf-processing/scripts/extract-text.py

File: database-queries/scripts/explain-query.sh

#!/bin/bash
QUERY="$1"
DB_NAME="${2:-postgres}"
if [ -z "$QUERY" ]; then
echo "Error: No query provided" >&2
exit 1
fi
echo "Analyzing query execution plan..."
psql -d "$DB_NAME" -c "EXPLAIN ANALYZE $QUERY"
  1. Accept arguments: Use command line arguments for input
  2. Output JSON: Return structured data for easy parsing
  3. Error handling: Send errors to stderr, exit with non-zero status
  4. Dependencies: Check for required tools/libraries
  5. Timeouts: Keep operations under 30 seconds
# Good: Accept input as arguments
INPUT_FILE = sys.argv[1] if len(sys.argv) > 1 else None
# Good: Output structured data
print(json.dumps({"result": data, "success": True}))
# Good: Errors to stderr
print("Error processing file", file=sys.stderr)

File: stripe-api/references/api-reference.md

# Stripe API Reference
## Authentication
All API requests require authentication using your secret key:
```bash
curl https://api.stripe.com/v1/charges \
-u sk_test_your_key:
```
## Create a Payment Intent
**Endpoint:** `POST /v1/payment_intents`
**Parameters:**
- `amount` (required): Amount in cents
- `currency` (required): Three-letter ISO code
- `payment_method_types` (required): Array of payment methods
**Example:**
```bash
curl https://api.stripe.com/v1/payment_intents \
-u sk_test_your_key: \
-d amount=1000 \
-d currency=usd \
-d "payment_method_types[]"=card
```

Tell the agent about reference files:

---
name: stripe-api
description: Work with Stripe payment APIs
---
## Reference Documentation
For detailed API documentation, use the `read_skill_reference` tool with:
- skillName: "stripe-api"
- referencePath: "api-reference.md"
For authentication examples, use:
- referencePath: "guides/authentication.md"

✅ Good names:

  • pdf-processing
  • web-scraping
  • database-tools
  • api-testing
  • code-review

❌ Invalid names:

  • PDF-Processing (uppercase not allowed)
  • pdf_processing (underscores not allowed)
  • pdf processing (spaces not allowed)
  • -pdf (cannot start with hyphen)
  • pdf- (cannot end with hyphen)
  • pdf--processing (consecutive hyphens not allowed)

Rules:

  • 1-64 characters
  • Lowercase letters, numbers, and hyphens only
  • Must not start or end with hyphen
  • No consecutive hyphens

Tarsk lists every eligible skill’s name, description, and when-to-use text in the system prompt under an # Available Skills section. The agent reads that catalog, decides which skills look relevant to the current task, and calls the read_skill tool to load the full SKILL.md instructions on demand. Full instructions are injected directly only for explicit /skill-name or //skill-name invocations and for skills listed in the thread’s enabledSkills.

Manual-Only Skills (disable-model-invocation)

Section titled “Manual-Only Skills (disable-model-invocation)”

Set disable-model-invocation: true when a skill should not appear in the Available Skills catalog. The agent will only receive the skill when you invoke it explicitly:

---
name: deploy
description: Deploy the application to staging or production
disable-model-invocation: true
---

Invoke with a slash command in your message:

/deploy staging

Bundled skills use a double slash: //skill-creator.

In Settings → Plugins → Skills, each installed skill shows a puzzle icon to the left of its name: click it to toggle disable-model-invocation without editing the file, and hover it to see roughly how many tokens the skill’s description adds to the context window.

The Available Skills catalog and thread enabledSkills both skip skills with this flag. Only an explicit /skill-name (or //skill-name) in the message activates them.

Thread records can store enabledSkills and disabledSkills overrides in the database, but the app does not expose a UI for these fields yet.

Skills use progressive disclosure to minimize context usage:

1. Startup (always loaded):

  • Skill name and description
  • ~100 tokens per skill

2. Activation (explicit invocation or on-demand read_skill):

  • Full SKILL.md instructions
  • <5000 tokens per skill

3. On-demand (when agent requests):

  • Reference files via read_skill_reference
  • Loaded only when needed

Scripts have a 30-second timeout by default. Set the timeout argument on execute_skill_script to allow more time. Printing progress does not extend the timeout.

Progress output

import sys
for i in range(100):
process_chunk(i)
print(f"Progress: {i}%", file=sys.stderr)
sys.stderr.flush()

Background processing

#!/bin/bash
nohup long-running-process.sh > output.log 2>&1 &
PID=$!
echo "Started process: $PID"
echo "Check output: tail -f output.log"

Check the skill name:

  • Must match directory name exactly
  • Lowercase, alphanumeric, hyphens only

Check frontmatter:

# ❌ Missing closing delimiter
name: my-skill
description: My skill
# ❌ Name mismatch
Directory: my-skill/
Frontmatter: name: different-name
# ✅ Correct
---
name: my-skill
description: My skill
---

Write a clear description: The agent reads the description and when_to_use text to decide when the skill helps. State what the skill does and when to use it.

Check permissions:

Terminal window
chmod +x ~/.agents/skills/my-skill/scripts/my-script.sh

Check dependencies:

try:
import PyPDF2
except ImportError:
print("Error: PyPDF2 not installed. Run: pip install PyPDF2", file=sys.stderr)
sys.exit(1)
  • Create skills folder: mkdir -p ~/.agents/skills
  • Create your first skill (e.g., code-review)
  • Write clear instructions in SKILL.md
  • Test activation with a relevant task
  • Add scripts for specialized tools (optional)
  • Add reference docs for detailed info (optional)
  • Create project-specific skills in .agents/skills/
  • Commit project skills to git for your team

Skills transform Tarsk from a general-purpose AI assistant into a specialized tool tailored to your specific technologies, workflows, and requirements.