← Back to PRs

#21712: feat(config): add custom commands to CommandsSchema

by Jimmysnielsen open 2026-02-20 08:30 View on GitHub →
size: M
## Summary Adds `commands.custom` to the Zod config schema so the existing custom commands runtime handler (`commands-custom.ts`) can actually be used. The handler, interpolation logic (`${ARGS}`, `${WORKSPACE}`), and tests all exist already — the only gap was that `CommandsSchema` used `.strict()` and didn't include a `custom` field, so the config was rejected at validation time. ## Changes - Added `CustomCommandSchema` (description, exec, reply, ownerOnly) - Added `custom: z.record(z.string(), CustomCommandSchema).optional()` to `CommandsSchema` ## Config Example ```json { "commands": { "custom": { "dnd": { "description": "Toggle Do Not Disturb", "exec": "bash ${WORKSPACE}/skills/dnd/scripts/toggle.sh ${ARGS}", "reply": true } } } } ``` ## Testing - All 417 config tests pass - All 7 commands-custom tests pass - Type-check clean (`pnpm tsgo`) Closes #21700 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR closes the gap between the existing custom commands runtime handler and the Zod config schema validation. The handler (`commands-custom.ts`) and its comprehensive test suite already existed, but `CommandsSchema` used `.strict()` without including a `custom` field, causing config validation to reject valid custom command configurations. The implementation adds: - `CustomCommandSchema` with fields for `description`, `exec`, `reply`, and `ownerOnly` - `custom: z.record(z.string(), CustomCommandSchema).optional()` to `CommandsSchema` - Handler registration in `commands-core.ts` (positioned after plugin commands, before bash) - Field label in `schema.labels.ts` - Type definitions in `types.messages.ts` The handler includes security controls: `ownerOnly` defaults to requiring authorized senders (line 55 in `commands-custom.ts`), args are passed via string interpolation with `${ARGS}` and `${WORKSPACE}` placeholders, and commands timeout after 10 seconds. <h3>Confidence Score: 3/5</h3> - This PR is safe to merge with caution - addresses the config validation gap, but has a shell injection vulnerability - Score reflects that the PR correctly implements the schema plumbing and has comprehensive tests, but the `interpolateExec` function doesn't escape user-provided arguments before shell execution, creating a command injection risk for authorized users. The feature is owner-restricted by default which limits exposure, but the vulnerability should be fixed. - Pay close attention to `src/auto-reply/reply/commands-custom.ts` - the interpolation logic needs shell escaping <sub>Last reviewed commit: 94f56d2</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs