Skills & custom commands
Teach Syntic Code a task once and reuse it forever. Both skills and custom commands are Markdown files holding a prompt; the difference is who can start them.
| Skill | Custom command | |
|---|---|---|
| Lives in | A folder with a SKILL.md file | A single .md file in a commands/ folder |
| You run it with | /skill-name | /command-name |
| The agent can start it by itself | Yes, when your request matches its description | Yes, through the same skill list |
| Can bring its own files (scripts, templates) | Yes, in its folder | No |
| Best for | Know-how the agent should apply when relevant (“how we write migrations”) | A prompt you fire on demand (“/release-notes v2.3”) |
Write a skill
Create .syntic/skills/changelog/SKILL.md:
---
description: Draft a changelog entry for the current branch
when_to_use: When the user asks for release notes or a changelog entry
argument-hint: <version>
allowed-tools: Bash(git log:*), Read, Edit
---
Write a changelog entry for version $1.
1. Read CHANGELOG.md to match its style.
2. Look at the commits since the last tag with git log.
3. Group the changes into Added, Changed and Fixed, in plain language.
4. Insert the entry at the top of CHANGELOG.md.The folder name (changelog) is the skill’s name. Run it with /changelog 2.4.0, or just ask “write the changelog entry for 2.4.0” and the agent picks it up. Skills are rescanned every couple of seconds, so a new or edited skill is available almost immediately; /reload-skills rescans right away.
Where skills are found
| Folder | Available |
|---|---|
.syntic/skills/ in the project | To everyone in this repository (once the folder is trusted). Skill folders found deeper in the project are added as the session works there. |
~/.syntic/skills/ | To you, everywhere. |
skills/ in a folder added with /add-dir | In that session. |
A plugin’s skills/ folder | While the plugin is enabled. |
| Your organization’s managed skills folder | To everyone on the machine. |
When two skills share a name, your user skill wins over a project skill, which wins over a plugin skill. /skills lists every skill the session can see; Enter puts its command in the prompt.
Skill frontmatter
| Key | Meaning |
|---|---|
description | One line saying what it does. Without it, the first line of the body is used. |
when_to_use | A hint for when the agent should run it (shown instead of the description). |
argument-hint | Shown after the name in the / menu, for example <version>. |
arguments | Names for arguments, so the body can use $version instead of $1. |
allowed-tools | Tools that run without asking while the skill runs. Listing Bash also enables inline shell. |
model | Model for the skill’s turn (inherit keeps the session’s). |
effort | Reasoning effort for the skill’s turn. |
context | fork runs the skill in a subagent and returns its report; inline (default) runs it in the conversation. |
agent | Which subagent type a forked skill uses. |
paths | Glob patterns. The skill is only offered once the session touches a matching file. |
user-invocable | false hides it from the / menu. |
disable-model-invocation | true: only you can run it. |
shell | bash or powershell for inline shell. |
hooks | Hooks that apply while the skill runs. |
Placeholders
| Write | Becomes |
|---|---|
$ARGUMENTS | Everything typed after the name. |
$1, $2, … (also $0 for the first) | One argument each. Quotes keep words together. |
$ARGUMENTS[0] | The first argument, counting from zero. |
$name | A named argument from arguments. |
${SYNTIC_SKILL_DIR} | The skill’s own folder, for scripts and templates you ship with it. |
${SYNTIC_SESSION_ID} | The session id. |
If the body uses no placeholder and you pass arguments, they are added at the end.
Inline shell
!`git branch --show-current` in the body runs that command and puts its output into the prompt before it is sent. A fenced block that starts with ```! does the same for several lines. Inline shell only runs when allowed-tools includes Bash, each command still goes through your permission rules, and "disableSkillShellExecution": true in any settings file turns it off everywhere.
Custom commands follow the same rule: their inline shell runs only when the command’s allowed-tools includes Bash. When it is not allowed (or disableSkillShellExecution is on), the directives are left as plain text, nothing runs, and the session tells you how many were skipped and why.
Write a custom command
Create .syntic/commands/fix-issue.md:
---
description: Fix a GitHub issue end to end
argument-hint: <issue number>
allowed-tools: Bash(gh issue view:*)
---
Fix issue #$1. Read it with `gh issue view $1`, reproduce the problem,
fix it, add a test, and summarize the change in two sentences.Now /fix-issue 812 runs it.
| Folder | Scope |
|---|---|
~/.syntic/commands/ | You, in every project. |
.syntic/commands/ in the project and its parents up to the git root | The project. The closest folder wins a name clash. |
commands/ in a folder added with /add-dir | That session. |
A plugin’s commands/ folder | Named /<plugin>:<name>. |
Subfolders become namespaces: .syntic/commands/db/reset.md is /db:reset, and you can also type just /reset if no other command ends that way. Project commands win over your user commands, and both win over plugin commands. A custom command can never replace a built-in one.
Commands accept the same placeholders and most of the same frontmatter as skills (description, argument-hint, arguments, allowed-tools, model, effort, when_to_use, disable-model-invocation, user-invocable, hooks). For context, paths or bundled files, use a skill.
You can also reference files in the body with @path/to/file; their contents are included when the command runs.
Control visibility
Hide or limit any skill, including built-in ones, from any settings file:
{ "skillOverrides": { "deploy": "user-invocable-only", "legacy-notes": "off", "style-guide": "name-only" } }| Value | Effect |
|---|---|
off | Gone entirely. |
user-invocable-only | You can run it; the agent cannot. |
name-only | Listed to the agent by name only, without its description. |
/skill-doctor shows which skills take up context and which went unused, so you can prune. Environment switches such as SYNTIC_SKILLS_DISABLE_PROJECT and SYNTIC_SKILLS_BARE are listed on Environment variables.
Share them
Put skills, commands, agents and hooks in a plugin to share them across repositories or with your team. To scaffold one around a first skill: syntic plugin init <name>.