Skip to content

Conversation

@alexandrevilain
Copy link
Contributor

Context

Implement custom commands feature allowing users to create reusable slash commands from markdown files stored in global (~/.kilocode/commands/) or project-specific (.kilocode/commands/) directories. Commands support argument substitution, automatic mode/model switching, and YAML frontmatter configuration.

Implementation

Users drop markdown files in ~/.kilocode/commands/ or .kilocode/commands/, and those become slash commands. That's it.

Commands loading steps:

  • On startup, I scan both directories for .md files
  • Parse each file with gray-matter to extract YAML frontmatter
  • Project-level commands override global ones (so you can customize per-project)

The markdown format:

---
description: What the command does
arguments: [arg1, arg2]
mode: code
model: opus
---

Your prompt template here with $1 and $2 for arguments

When you run the command:

  1. Replace $1, $2, etc. with the actual arguments you passed
  2. Switch to the specified mode/model if provided
  3. Send the processed text as a new chat message

Decisions

Mardown: Same as opencode, claude code, simple to write.

Directories: We already have this pattern for skills (~/.kilocode/skills/ and .kilocode/skills/), so just reused the same convention. Users already understand it.

Arguments substitution: Tried to keep it dumb - just replace $1 with the first arg, $ARGUMENTS with all args. No fancy templating engine needed.

Error handling: If a directory doesn't exist, fine. If model switching fails, warn but keep going. Don't break the whole feature because of one bad file.

Screenshots

Here is an example with the following custom command:

---
description: Example command that switches mode, model and parses arguments.
mode: ask
model: x-ai/grok-code-fast-1
arguments:
  - what
---

Only say "$1"
custom-commands-light.mp4

How to Test

Create custom commands in ~/.kilocode/commands/or .kilocode/commands/ and run kilo.
You can use them and show commands help

Get in Touch

Discord: alexandrevilain.

@changeset-bot
Copy link

changeset-bot bot commented Jan 18, 2026

🦋 Changeset detected

Latest commit: 01e9014

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@kilocode/cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@alexandrevilain alexandrevilain force-pushed the feat/cli/custom-commands branch from 65cffcc to d084421 Compare January 18, 2026 13:51
})

describe("getCustomCommands", () => {
const mockCwd = "/mock/project"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests might fail on Windows

@marius-kilocode
Copy link
Collaborator

Cool feature @alexandrevilain! We just need to get those edge cases right.

@marius-kilocode marius-kilocode added the CLI Kilo Code CLI label Jan 18, 2026
@alexandrevilain alexandrevilain force-pushed the feat/cli/custom-commands branch from d084421 to 42fb14f Compare January 18, 2026 19:05
@alexandrevilain
Copy link
Contributor Author

Thanks for the review @marius-kilocode !

I've addressed all your comments except for the failing tests on Windows. Since I don't have a Windows development environment, I can't confirm whether these tests are actually failing or not. However, given that the tests use mocked implementations for os.homedir() and fs.readdir(), they should theoretically work cross-platform.

Feel free to let me know what kind of issues you're anticipating on Windows with this approach, and I'll be happy to adjust accordingly!

Implement custom commands feature allowing users to create reusable slash commands
from markdown files stored in global (~/.kilocode/commands/) or project-specific
(.kilocode/commands/) directories. Commands support argument substitution,
automatic mode/model switching, and YAML frontmatter configuration.

- Add documentation for custom commands in CLI docs
- Implement custom command loading, parsing, and execution logic
- Add comprehensive test suite for custom commands functionality
- Integrate custom commands initialization into the UI startup process
@alexandrevilain alexandrevilain force-pushed the feat/cli/custom-commands branch from 42fb14f to 8450f6d Compare January 18, 2026 19:11
const entries = await fs.readdir(dirPath, { withFileTypes: true })

for (const entry of entries) {
if (!entry.isFile() || !entry.name.toLowerCase().endsWith(".md")) continue
Copy link
Collaborator

@marius-kilocode marius-kilocode Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexandrevilain I think you misunderstood me here. The .md file was just an example. We need to validate here if the format for a custom slash command is correct. Maybe a regex would make sense.

Good:
/review
/review-this

Bad:
/this.is.bad
/file.txt
/$#()%$#)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marius-kilocode this was the purpose of isValidCommandName. Isn't it sufficient ?

Maybe I can rework it to become isValidCommandFilename and validate against ^[a-zA-Z0-9][a-zA-Z0-9-]*\.md$. WDYT ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I misread the regex. I also tested it one more time. The change looks good to go. Thanks a lot!

@marius-kilocode marius-kilocode enabled auto-merge (squash) January 19, 2026 08:35
@marius-kilocode
Copy link
Collaborator

Thanks for the contribution @alexandrevilain!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLI Kilo Code CLI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants