11package cmd
22
33import (
4+ "errors"
45 "os"
56 "path/filepath"
67 "strings"
78
89 "github.com/nicksenap/grove/internal/config"
910 "github.com/nicksenap/grove/internal/console"
1011 "github.com/nicksenap/grove/internal/discover"
12+ "github.com/nicksenap/grove/internal/lifecycle"
1113 "github.com/nicksenap/grove/internal/models"
1214 "github.com/nicksenap/grove/internal/picker"
1315 "github.com/nicksenap/grove/internal/workspace"
1416 "github.com/spf13/cobra"
1517)
1618
1719var (
18- createBranch string
19- createRepos string
20- createPreset string
21- createAll bool
22- createCopyClaudeMD * bool
20+ createBranch string
21+ createRepos string
22+ createPreset string
23+ createAll bool
2324)
2425
2526var createCmd = & cobra.Command {
@@ -143,25 +144,14 @@ var createCmd = &cobra.Command{
143144 exitError (err .Error ())
144145 }
145146
146- // Copy CLAUDE.md if requested
147+ // Fire post_create hook if configured
147148 wsPath := filepath .Join (cfg .WorkspaceDir , name )
148- if createCopyClaudeMD != nil {
149- if * createCopyClaudeMD {
150- copyCLAUDEmd (repoMap , repoNames , wsPath )
151- }
152- } else if console .IsTerminal (os .Stdin ) {
153- // Auto-detect: check if any repo has a CLAUDE.md
154- for _ , repoName := range repoNames {
155- if src , ok := repoMap [repoName ]; ok {
156- claudeMD := filepath .Join (src , "CLAUDE.md" )
157- if _ , err := os .Stat (claudeMD ); err == nil {
158- if console .Confirm ("Copy CLAUDE.md into workspace?" , true ) {
159- copyCLAUDEmd (repoMap , repoNames , wsPath )
160- }
161- break
162- }
163- }
164- }
149+ vars := lifecycle.Vars {Name : name , Path : wsPath , Branch : branch }
150+ if err := lifecycle .Run ("post_create" , vars ); errors .Is (err , lifecycle .ErrNoHook ) {
151+ // TODO: remove when matured — legacy fallback for users without [hooks] config.
152+ copyParentCLAUDEmd (wsPath )
153+ } else if err != nil {
154+ console .Warningf ("post_create hook failed: %s" , err )
165155 }
166156 },
167157}
@@ -171,39 +161,20 @@ func init() {
171161 createCmd .Flags ().StringVarP (& createRepos , "repos" , "r" , "" , "Comma-separated repo names" )
172162 createCmd .Flags ().StringVarP (& createPreset , "preset" , "p" , "" , "Use named preset" )
173163 createCmd .Flags ().BoolVar (& createAll , "all" , false , "Use all discovered repos" )
174- createCmd .Flags ().Bool ("copy-claude-md" , false , "Copy CLAUDE.md into workspace dir" )
175- createCmd .Flags ().Bool ("no-copy-claude-md" , false , "Don't copy CLAUDE.md" )
176164
177165 createCmd .RegisterFlagCompletionFunc ("repos" , completeRepoNames )
178166 createCmd .RegisterFlagCompletionFunc ("preset" , completePresetNames )
179-
180- // Resolve --copy-claude-md / --no-copy-claude-md
181- createCmd .PreRun = func (cmd * cobra.Command , args []string ) {
182- if cmd .Flags ().Changed ("copy-claude-md" ) {
183- v := true
184- createCopyClaudeMD = & v
185- } else if cmd .Flags ().Changed ("no-copy-claude-md" ) {
186- v := false
187- createCopyClaudeMD = & v
188- }
189- }
190167}
191168
192- func copyCLAUDEmd (repoMap map [string ]string , repoNames []string , wsPath string ) {
193- for _ , repoName := range repoNames {
194- src , ok := repoMap [repoName ]
195- if ! ok {
196- continue
197- }
198- claudeMD := filepath .Join (src , "CLAUDE.md" )
199- data , err := os .ReadFile (claudeMD )
200- if err != nil {
201- continue
202- }
203- dst := filepath .Join (wsPath , "CLAUDE.md" )
204- os .WriteFile (dst , data , 0o644 )
205- return // only copy from first repo that has it
169+
170+ // TODO: remove when matured — legacy fallback for users without [hooks] config.
171+ func copyParentCLAUDEmd (wsPath string ) {
172+ src := filepath .Join (wsPath , ".." , "CLAUDE.md" )
173+ data , err := os .ReadFile (src )
174+ if err != nil {
175+ return
206176 }
177+ os .WriteFile (filepath .Join (wsPath , "CLAUDE.md" ), data , 0o644 )
207178}
208179
209180func deriveName (branch string ) string {
0 commit comments