@@ -107,6 +107,32 @@ export namespace Config {
107107 }
108108 throw new InvalidError ( { path : item } , { cause : parsed . error } )
109109 }
110+
111+ // Load command markdown files
112+ result . command = result . command || { }
113+ const markdownCommands = [
114+ ...( await Filesystem . globUp ( "command/*.md" , Global . Path . config , Global . Path . config ) ) ,
115+ ...( await Filesystem . globUp ( ".opencode/command/*.md" , app . path . cwd , app . path . root ) ) ,
116+ ]
117+ for ( const item of markdownCommands ) {
118+ const content = await Bun . file ( item ) . text ( )
119+ const md = matter ( content )
120+ if ( ! md . data ) continue
121+
122+ const config = {
123+ name : path . basename ( item , ".md" ) ,
124+ ...md . data ,
125+ template : md . content . trim ( ) ,
126+ }
127+ const parsed = Command . safeParse ( config )
128+ if ( parsed . success ) {
129+ result . command = mergeDeep ( result . command , {
130+ [ config . name ] : parsed . data ,
131+ } )
132+ continue
133+ }
134+ throw new InvalidError ( { path : item } , { cause : parsed . error } )
135+ }
110136 // Migrate deprecated mode field to agent field
111137 for ( const [ name , mode ] of Object . entries ( result . mode ) ) {
112138 result . agent = mergeDeep ( result . agent ?? { } , {
@@ -192,6 +218,14 @@ export namespace Config {
192218 export const Permission = z . union ( [ z . literal ( "ask" ) , z . literal ( "allow" ) , z . literal ( "deny" ) ] )
193219 export type Permission = z . infer < typeof Permission >
194220
221+ export const Command = z . object ( {
222+ template : z . string ( ) ,
223+ description : z . string ( ) . optional ( ) ,
224+ agent : z . string ( ) . optional ( ) ,
225+ model : z . string ( ) . optional ( ) ,
226+ } )
227+ export type Command = z . infer < typeof Command >
228+
195229 export const Agent = z
196230 . object ( {
197231 model : z . string ( ) . optional ( ) ,
@@ -305,6 +339,7 @@ export namespace Config {
305339 theme : z . string ( ) . optional ( ) . describe ( "Theme name to use for the interface" ) ,
306340 keybinds : Keybinds . optional ( ) . describe ( "Custom keybind configurations" ) ,
307341 tui : TUI . optional ( ) . describe ( "TUI specific settings" ) ,
342+ command : z . record ( z . string ( ) , Command ) . optional ( ) ,
308343 plugin : z . string ( ) . array ( ) . optional ( ) ,
309344 snapshot : z . boolean ( ) . optional ( ) ,
310345 share : z
0 commit comments