From 23d8f86762e7cae439e8e8544bcd826a880c7be0 Mon Sep 17 00:00:00 2001 From: milldr Date: Tue, 24 Feb 2026 16:41:37 -0500 Subject: [PATCH 1/2] Fix init next-step hint to use 'flow edit state' --- internal/cmd/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/init.go b/internal/cmd/init.go index 3786e85..efc1c7e 100644 --- a/internal/cmd/init.go +++ b/internal/cmd/init.go @@ -51,7 +51,7 @@ func newInitCmd(svc *workspace.Service) *cobra.Command { if name != "" { ref = name } - ui.Printf("\n Next: %s\n", ui.Code("flow state "+ref)) + ui.Printf("\n Next: %s\n", ui.Code("flow edit state "+ref)) return nil }, From 708b9b1d40cb2d24795d6135d257b4d34d76f52d Mon Sep 17 00:00:00 2001 From: milldr Date: Tue, 24 Feb 2026 16:55:23 -0500 Subject: [PATCH 2/2] Set up Claude agent files during workspace create so skills are available immediately after init --- internal/workspace/workspace.go | 11 +++++- internal/workspace/workspace_test.go | 51 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/internal/workspace/workspace.go b/internal/workspace/workspace.go index 7a9e3ac..2c3f38e 100644 --- a/internal/workspace/workspace.go +++ b/internal/workspace/workspace.go @@ -72,7 +72,16 @@ func (s *Service) Create(id string, st *state.State) error { return err } - return state.Save(s.Config.StatePath(id), st) + if err := state.Save(s.Config.StatePath(id), st); err != nil { + return err + } + + // Set up Claude agent files immediately so skills are available before render + if err := agents.SetupWorkspaceClaude(wsDir, s.Config.AgentsDir, st, id); err != nil { + return fmt.Errorf("setting up claude files: %w", err) + } + + return nil } // List returns info for all workspaces. diff --git a/internal/workspace/workspace_test.go b/internal/workspace/workspace_test.go index fb9b3db..e5149c0 100644 --- a/internal/workspace/workspace_test.go +++ b/internal/workspace/workspace_test.go @@ -635,6 +635,57 @@ func TestGenerateUniqueIDAvoidsExisting(t *testing.T) { } } +func TestCreateSetsUpClaudeFiles(t *testing.T) { + svc, _ := testService(t) + + st := state.NewState("create-claude", "Test Claude setup on create", []state.Repo{ + {URL: "github.com/org/repo-a", Branch: "main", Path: "./repo-a"}, + {URL: "github.com/org/repo-b", Branch: "feat/x", Path: "./repo-b"}, + }) + + if err := svc.Create("create-claude-ws", st); err != nil { + t.Fatal(err) + } + + wsDir := svc.Config.WorkspacePath("create-claude-ws") + + // Workspace CLAUDE.md should exist with repo info + data, err := os.ReadFile(filepath.Join(wsDir, "CLAUDE.md")) + if err != nil { + t.Fatal("workspace CLAUDE.md not created by Create()") + } + content := string(data) + if !strings.Contains(content, "create-claude") { + t.Error("workspace CLAUDE.md missing name") + } + if !strings.Contains(content, "repo-a") { + t.Error("workspace CLAUDE.md missing repo-a") + } + if !strings.Contains(content, "repo-b") { + t.Error("workspace CLAUDE.md missing repo-b") + } + + // .claude/CLAUDE.md should be a symlink to shared + target, err := os.Readlink(filepath.Join(wsDir, ".claude", "CLAUDE.md")) + if err != nil { + t.Fatal(".claude/CLAUDE.md symlink not created by Create()") + } + expected := filepath.Join(svc.Config.AgentsDir, "claude", "CLAUDE.md") + if target != expected { + t.Errorf(".claude/CLAUDE.md target = %q, want %q", target, expected) + } + + // .claude/skills should be a symlink to shared + target, err = os.Readlink(filepath.Join(wsDir, ".claude", "skills")) + if err != nil { + t.Fatal(".claude/skills symlink not created by Create()") + } + expected = filepath.Join(svc.Config.AgentsDir, "claude", "skills") + if target != expected { + t.Errorf(".claude/skills target = %q, want %q", target, expected) + } +} + func TestRenderCreatesClaudeFiles(t *testing.T) { svc, _ := testService(t) ctx := context.Background()