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.

SkillCustom command
Lives inA folder with a SKILL.md fileA single .md file in a commands/ folder
You run it with/skill-name/command-name
The agent can start it by itselfYes, when your request matches its descriptionYes, through the same skill list
Can bring its own files (scripts, templates)Yes, in its folderNo
Best forKnow-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

FolderAvailable
.syntic/skills/ in the projectTo 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-dirIn that session.
A plugin’s skills/ folderWhile the plugin is enabled.
Your organization’s managed skills folderTo 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

KeyMeaning
descriptionOne line saying what it does. Without it, the first line of the body is used.
when_to_useA hint for when the agent should run it (shown instead of the description).
argument-hintShown after the name in the / menu, for example <version>.
argumentsNames for arguments, so the body can use $version instead of $1.
allowed-toolsTools that run without asking while the skill runs. Listing Bash also enables inline shell.
modelModel for the skill’s turn (inherit keeps the session’s).
effortReasoning effort for the skill’s turn.
contextfork runs the skill in a subagent and returns its report; inline (default) runs it in the conversation.
agentWhich subagent type a forked skill uses.
pathsGlob patterns. The skill is only offered once the session touches a matching file.
user-invocablefalse hides it from the / menu.
disable-model-invocationtrue: only you can run it.
shellbash or powershell for inline shell.
hooksHooks that apply while the skill runs.

Placeholders

WriteBecomes
$ARGUMENTSEverything 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.
$nameA 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.

FolderScope
~/.syntic/commands/You, in every project.
.syntic/commands/ in the project and its parents up to the git rootThe project. The closest folder wins a name clash.
commands/ in a folder added with /add-dirThat session.
A plugin’s commands/ folderNamed /<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" } }
ValueEffect
offGone entirely.
user-invocable-onlyYou can run it; the agent cannot.
name-onlyListed 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>.