Commit b9e4814

bryfry <bryon@fryer.io>
2025-09-24 20:25:51
start feat/001_init
1 parent 08c012f
cmd/init.go
@@ -1,24 +1,279 @@
 package cmd
 
 import (
+	"fmt"
+	"os"
+	"os/exec"
+	"time"
+
+	"github.com/go-git/go-billy/v5/osfs"
+	"github.com/go-git/go-git/v5"
+	"github.com/go-git/go-git/v5/config"
+	"github.com/go-git/go-git/v5/plumbing"
+	"github.com/go-git/go-git/v5/plumbing/object"
 	"github.com/spf13/cobra"
 )
 
 func NewInitCmd() *cobra.Command {
+	var setupWorktree bool
 
 	var cmd = &cobra.Command{
-		Use:   "tissue init",
-		Short: "init tissues for the current repo",
-		Long:  `<long description>`,
-		RunE:  initRunE,
+		Use:   "init",
+		Short: "Initialize tissue issue tracking in the current repo",
+		Long: `Initialize tissue issue tracking by creating an orphan 'issues' branch
+with proper structure and optionally setting up a git worktree for easy access.`,
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return initRunE(cmd, args, setupWorktree)
+		},
 	}
 
 	// flags
-	// cmd.Flags()
+	cmd.Flags().BoolVar(&setupWorktree, "setup-worktree", false, "Create a git worktree for the issues branch")
 
 	return cmd
 }
 
-func initRunE(cmd *cobra.Command, args []string) error {
+func initRunE(cmd *cobra.Command, args []string, setupWorktree bool) error {
+	// Step 1: Open and validate repository
+	fmt.Println("Initializing tissue issue tracking...")
+
+	repo, err := git.PlainOpen(".")
+	if err != nil {
+		return fmt.Errorf("failed to open repository: %w\nMake sure you're in a git repository", err)
+	}
+
+	// Store current branch to return to later
+	head, err := repo.Head()
+	if err != nil {
+		return fmt.Errorf("failed to get current branch: %w", err)
+	}
+	originalBranch := head.Name()
+
+	// Check if issues branch already exists
+	_, err = repo.Reference(plumbing.ReferenceName("refs/heads/issues"), false)
+	if err == nil {
+		return fmt.Errorf("issues branch already exists. Use 'tissue status' to check current setup")
+	}
+
+	// Step 2: Create orphan branch
+	fmt.Println("Creating orphan 'issues' branch...")
+	orphanRef := plumbing.NewSymbolicReference(
+		plumbing.HEAD,
+		plumbing.ReferenceName("refs/heads/issues"),
+	)
+	err = repo.Storer.SetReference(orphanRef)
+	if err != nil {
+		return fmt.Errorf("failed to create orphan branch: %w", err)
+	}
+
+	// Step 3: Get worktree and initialize files
+	worktree, err := repo.Worktree()
+	if err != nil {
+		return fmt.Errorf("failed to get worktree: %w", err)
+	}
+
+	// Clear the working directory for orphan branch
+	fs := osfs.New(".")
+
+	// Create README.md
+	readmePath := "README.md"
+	readmeContent := `# Issue Tracker
+
+This branch contains all issues for this repository.
+Each issue is a markdown file with YAML frontmatter.
+
+## Structure
+
+Issues are stored as markdown files with the following frontmatter:
+
+` + "```yaml" + `
+---
+id: 001
+title: Issue title
+status: open
+type: bug|feature|task
+created: 2025-09-24
+assignee: username
+---
+` + "```" + `
+
+## Usage
+
+Use the tissue CLI to manage issues:
+- ` + "`tissue new`" + ` - Create a new issue
+- ` + "`tissue list`" + ` - List all issues
+- ` + "`tissue view <id>`" + ` - View an issue
+- ` + "`tissue update <id>`" + ` - Update an issue
+`
+	readmeFile, err := fs.Create(readmePath)
+	if err != nil {
+		return fmt.Errorf("failed to create README.md: %w", err)
+	}
+	_, err = readmeFile.Write([]byte(readmeContent))
+	if err != nil {
+		readmeFile.Close()
+		return fmt.Errorf("failed to write README.md: %w", err)
+	}
+	readmeFile.Close()
+
+	// Create .gitignore
+	gitignorePath := ".gitignore"
+	gitignoreContent := `# Ignore everything except markdown files and directories
+/*
+!*.md
+!*/
+!.gitignore
+`
+	gitignoreFile, err := fs.Create(gitignorePath)
+	if err != nil {
+		return fmt.Errorf("failed to create .gitignore: %w", err)
+	}
+	_, err = gitignoreFile.Write([]byte(gitignoreContent))
+	if err != nil {
+		gitignoreFile.Close()
+		return fmt.Errorf("failed to write .gitignore: %w", err)
+	}
+	gitignoreFile.Close()
+
+	// Stage files
+	fmt.Println("Creating initial structure...")
+	_, err = worktree.Add(readmePath)
+	if err != nil {
+		return fmt.Errorf("failed to stage README.md: %w", err)
+	}
+	_, err = worktree.Add(gitignorePath)
+	if err != nil {
+		return fmt.Errorf("failed to stage .gitignore: %w", err)
+	}
+
+	// Commit
+	commit, err := worktree.Commit("Initialize issues branch for issue tracking", &git.CommitOptions{
+		Author: &object.Signature{
+			Name:  "Tissue CLI",
+			Email: "tissue@example.com",
+			When:  time.Now(),
+		},
+	})
+	if err != nil {
+		return fmt.Errorf("failed to commit initial structure: %w", err)
+	}
+	fmt.Printf("Created initial commit: %s\n", commit.String()[:7])
+
+	// Step 4: Push to remote if it exists
+	remotes, err := repo.Remotes()
+	if err == nil && len(remotes) > 0 {
+		fmt.Println("Pushing to remote...")
+		err = repo.Push(&git.PushOptions{
+			RemoteName: "origin",
+			RefSpecs: []config.RefSpec{
+				config.RefSpec("refs/heads/issues:refs/heads/issues"),
+			},
+		})
+		if err != nil && err != git.NoErrAlreadyUpToDate {
+			fmt.Printf("Warning: Could not push to remote: %v\n", err)
+			fmt.Println("You can push manually later with: git push -u origin issues")
+		} else if err == nil {
+			fmt.Println("Pushed issues branch to remote")
+		}
+	}
+
+	// Step 5: Return to original branch
+	err = worktree.Checkout(&git.CheckoutOptions{
+		Branch: originalBranch,
+	})
+	if err != nil {
+		return fmt.Errorf("failed to return to original branch: %w", err)
+	}
+	fmt.Printf("Returned to branch: %s\n", originalBranch.Short())
+
+	// Step 6: Setup worktree if requested
+	if setupWorktree {
+		fmt.Println("Setting up git worktree...")
+
+		// TODO: Remove dependency on git CLI when go-git supports worktrees
+		// Track progress: https://github.com/go-git/go-git/pull/396
+		cmd := exec.Command("git", "worktree", "add", "issues", "issues")
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+		err := cmd.Run()
+		if err != nil {
+			return fmt.Errorf("failed to create worktree: %w\nYou can manually run: git worktree add issues issues", err)
+		}
+
+		// Add issues/ to .gitignore in main branch
+		gitignoreMainPath := ".gitignore"
+		var gitignoreContent []byte
+
+		// Check if .gitignore exists
+		if file, err := os.Open(gitignoreMainPath); err == nil {
+			defer file.Close()
+			info, _ := file.Stat()
+			gitignoreContent = make([]byte, info.Size())
+			file.Read(gitignoreContent)
+		}
+
+		// Append issues/ if not already present
+		gitignoreStr := string(gitignoreContent)
+		if !contains(gitignoreStr, "issues/") {
+			if len(gitignoreStr) > 0 && gitignoreStr[len(gitignoreStr)-1] != '\n' {
+				gitignoreStr += "\n"
+			}
+			gitignoreStr += "issues/\n"
+
+			err = os.WriteFile(gitignoreMainPath, []byte(gitignoreStr), 0644)
+			if err != nil {
+				return fmt.Errorf("failed to update .gitignore: %w", err)
+			}
+
+			// Stage and commit .gitignore update
+			_, err = worktree.Add(gitignoreMainPath)
+			if err != nil {
+				fmt.Printf("Warning: Could not stage .gitignore: %v\n", err)
+			} else {
+				_, err = worktree.Commit("Add issues worktree to gitignore", &git.CommitOptions{
+					Author: &object.Signature{
+						Name:  "Tissue CLI",
+						Email: "tissue@example.com",
+						When:  time.Now(),
+					},
+				})
+				if err != nil {
+					fmt.Printf("Warning: Could not commit .gitignore update: %v\n", err)
+				}
+			}
+		}
+
+		fmt.Println("Git worktree created at ./issues")
+	}
+
+	fmt.Println("\n✓ Tissue initialized successfully!")
+	fmt.Println("\nNext steps:")
+	if !setupWorktree {
+		fmt.Println("  - Run 'tissue init --setup-worktree' to create a worktree")
+		fmt.Println("  - Or manually: git worktree add issues issues")
+	}
+	fmt.Println("  - Create your first issue: tissue new")
+	fmt.Println("  - List issues: tissue list")
+	fmt.Println("  - Check status: tissue status")
+
 	return nil
 }
+
+func contains(s, substr string) bool {
+	return len(s) > 0 && len(substr) > 0 &&
+		(s == substr ||
+		len(s) > len(substr) &&
+		(s[:len(substr)] == substr ||
+		s[len(s)-len(substr):] == substr ||
+		len(s) > len(substr)+1 &&
+		containsInMiddle(s, substr)))
+}
+
+func containsInMiddle(s, substr string) bool {
+	for i := 1; i < len(s)-len(substr); i++ {
+		if s[i:i+len(substr)] == substr {
+			return true
+		}
+	}
+	return false
+}
docs/cmd/init.md
@@ -5,7 +5,6 @@ Initialize tissue issue tracking in a git repository.
 ## Tissue Command
 ```bash
 tissue init
-tissue init --setup-worktree
 ```
 
 ## Manual Workflow (bash + git)
.gitignore
@@ -1,1 +1,2 @@
 docs/book
+tissue
go.mod
@@ -3,7 +3,27 @@ module tissue
 go 1.24.2
 
 require (
+	dario.cat/mergo v1.0.0 // indirect
+	github.com/Microsoft/go-winio v0.6.2 // indirect
+	github.com/ProtonMail/go-crypto v1.1.6 // indirect
+	github.com/cloudflare/circl v1.6.1 // indirect
+	github.com/cyphar/filepath-securejoin v0.4.1 // indirect
+	github.com/emirpasic/gods v1.18.1 // indirect
+	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
+	github.com/go-git/go-billy/v5 v5.6.2 // indirect
+	github.com/go-git/go-git/v5 v5.16.2 // indirect
+	github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
+	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+	github.com/kevinburke/ssh_config v1.2.0 // indirect
+	github.com/pjbgf/sha1cd v0.3.2 // indirect
+	github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
+	github.com/skeema/knownhosts v1.3.1 // indirect
 	github.com/spf13/cobra v1.10.1 // indirect
 	github.com/spf13/pflag v1.0.9 // indirect
+	github.com/xanzy/ssh-agent v0.3.3 // indirect
+	golang.org/x/crypto v0.37.0 // indirect
+	golang.org/x/net v0.39.0 // indirect
+	golang.org/x/sys v0.32.0 // indirect
+	gopkg.in/warnings.v0 v0.1.2 // indirect
 )
go.sum
@@ -1,10 +1,76 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
+github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
+github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
+github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
+github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
+github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
+github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
+github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
+github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
 github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
 github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
 github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
 github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
+golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
README.md
@@ -46,7 +46,8 @@ mdbook serve docs
 tissue init
 
 # Clone a repository and set up tissue branch
-tissue clone https://github.com/user/repo.git
+git clone https://github.com/user/repo.git
+cd repo
 tissue init --setup-worktree
 ```