Function bodies 56 total
agent.DeleteMemoryFiles function · go · L12-L40 (29 LOC)internal/agent/memory.go
func DeleteMemoryFiles(treehousePath, nookID string) error {
// Validate nookID to prevent path traversal
if err := nook.ValidateNookID(nookID); err != nil {
return err
}
agentsPath := filepath.Join(treehousePath, "agents")
// Check if agents directory exists
if _, err := os.Stat(agentsPath); os.IsNotExist(err) {
return nil // Nothing to clean up
}
// Pattern: .treehouse/agents/*/memories/{nook-id}.md
memPattern := filepath.Join(agentsPath, "*", "memories", nookID+".md")
memFiles, _ := filepath.Glob(memPattern)
for _, f := range memFiles {
_ = os.Remove(f) // Best-effort removal
}
// Pattern: .treehouse/agents/*/sessions/{nook-id}.md
sessPattern := filepath.Join(agentsPath, "*", "sessions", nookID+".md")
sessFiles, _ := filepath.Glob(sessPattern)
for _, f := range sessFiles {
_ = os.Remove(f) // Best-effort removal
}
return nil
}board.LoadBoards function · go · L36-L67 (32 LOC)internal/board/board.go
func LoadBoards(nooksPath string) (*BoardsFile, error) {
boardsPath := filepath.Join(nooksPath, "boards.yaml")
data, err := os.ReadFile(boardsPath)
if err != nil {
if os.IsNotExist(err) {
// Return empty BoardsFile, not an error
return &BoardsFile{
Boards: make(map[string][]Pin),
}, nil
}
return nil, &BoardError{
Code: "BOARD_READ_FAILED",
Message: fmt.Sprintf("Failed to read boards.yaml: %v", err),
}
}
var boards map[string][]Pin
if err := yaml.Unmarshal(data, &boards); err != nil {
return nil, &BoardError{
Code: "BOARD_PARSE_FAILED",
Message: fmt.Sprintf("Failed to parse boards.yaml: %v", err),
}
}
// Initialize empty map if nil
if boards == nil {
boards = make(map[string][]Pin)
}
return &BoardsFile{Boards: boards}, nil
}board.SaveBoards function · go · L70-L145 (76 LOC)internal/board/board.go
func SaveBoards(nooksPath string, boards *BoardsFile) error {
boardsPath := filepath.Join(nooksPath, "boards.yaml")
// Marshal to YAML (just the map, not the wrapper struct)
data, err := yaml.Marshal(boards.Boards)
if err != nil {
return &BoardError{
Code: "BOARD_MARSHAL_FAILED",
Message: fmt.Sprintf("Failed to marshal boards: %v", err),
}
}
// Ensure nooks directory exists
if err := os.MkdirAll(nooksPath, 0755); err != nil {
return &BoardError{
Code: "BOARD_WRITE_FAILED",
Message: fmt.Sprintf("Failed to create nooks directory: %v", err),
}
}
// Create temp file in same directory for atomic rename
tempFile, err := os.CreateTemp(nooksPath, "boards.yaml.tmp.*")
if err != nil {
return &BoardError{
Code: "BOARD_WRITE_FAILED",
Message: fmt.Sprintf("Failed to create temp file: %v", err),
}
}
tempPath := tempFile.Name()
// Ensure temp file cleanup on error
defer func() {
if tempPath != "" {
os.Remove(tempPath)
}
}()
// Write board.AddPin function · go · L149-L165 (17 LOC)internal/board/board.go
func AddPin(boards *BoardsFile, nookID string, content string) string {
// Initialize boards map if nil
if boards.Boards == nil {
boards.Boards = make(map[string][]Pin)
}
// Generate RFC3339 timestamp
ts := time.Now().UTC().Format(time.RFC3339)
// Append pin to nook's board
boards.Boards[nookID] = append(boards.Boards[nookID], Pin{
Ts: ts,
Content: content,
})
return ts
}board.GetBoard function · go · L169-L180 (12 LOC)internal/board/board.go
func GetBoard(boards *BoardsFile, nookID string) []Pin {
if boards.Boards == nil {
return []Pin{}
}
pins, exists := boards.Boards[nookID]
if !exists {
return []Pin{}
}
return pins
}cmd.runBoard function · go · L40-L92 (53 LOC)internal/cmd/board.go
func runBoard() int {
// 1. Find treehouse (validates we're in an initialized repo)
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 2. Get current nook context
parentInfo, err := worktree.GetParentInfo(thInfo.TreehousePath)
if err != nil {
output.PrintError("BOARD_NOT_IN_NOOK", "Must be in a nook to view board")
return 1
}
// 3. Verify we're in a nook
if !parentInfo.IsNook {
output.PrintError("BOARD_NOT_IN_NOOK", "Must be in a nook to view board")
return 1
}
nookID := parentInfo.CurrentNook
// 4. Build nooks path and load boards
nooksPath := filepath.Join(thInfo.TreehousePath, "nooks")
boards, err := board.LoadBoards(nooksPath)
if err != nil {
boardErr, ok := err.(*board.BoardError)
if ok {
output.PrintError(boardErr.Code, boardErr.Message)
} else {
cmd.runFork function · go · L53-L212 (160 LOC)internal/cmd/fork.go
func runFork(name string) int {
// 1. Validate nook name
if err := nook.ValidateName(name); err != nil {
nookErr, ok := err.(*nook.NookError)
if ok {
output.PrintError(nookErr.Code, nookErr.Message)
} else {
output.PrintError("NOOK_NAME_INVALID", err.Error())
}
return 2
}
// 2. Find treehouse (this validates we're in an initialized repo)
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 3. Get git repo info for commit SHA
repoInfo, err := git.DetectRepo()
if err != nil {
gitErr, ok := err.(*git.GitError)
if ok {
output.PrintError(gitErr.Code, gitErr.Message)
return 3
}
output.PrintError("GIT_ERROR", err.Error())
return 3
}
// 3b. Validate commit SHA is present
if repoInfo.CommitSHA == "" {
output.PrintError("GIT_NO_COMMITS", "No commits foundGenerated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
cmd.setupClaudeCommandsSymlink function · go · L217-L242 (26 LOC)internal/cmd/fork.go
func setupClaudeCommandsSymlink(repoRoot, nookPath string) error {
// Check if source exists
sourcePath := filepath.Join(repoRoot, ".claude", "commands", "th")
if _, err := os.Stat(sourcePath); os.IsNotExist(err) {
return nil // th commands don't exist in base repo, skip
}
// Create .claude/commands/ directory in nook
nookCommandsDir := filepath.Join(nookPath, ".claude", "commands")
if err := os.MkdirAll(nookCommandsDir, 0755); err != nil {
return fmt.Errorf("failed to create .claude/commands: %w", err)
}
// Create relative symlink
// From: {nook}/.claude/commands/th
// To: {repo}/.claude/commands/th
// Relative: ../../../../../.claude/commands/th
symlinkPath := filepath.Join(nookCommandsDir, "th")
relTarget := filepath.Join("..", "..", "..", "..", "..", ".claude", "commands", "th")
if err := os.Symlink(relTarget, symlinkPath); err != nil {
return fmt.Errorf("failed to create symlink: %w", err)
}
return nil
}cmd.runHatAdd function · go · L68-L139 (72 LOC)internal/cmd/hat.go
func runHatAdd(name string, configJSON string) int {
// 1. Validate name format (lowercase, no special chars except hyphens)
sanitizedName := sanitizeHatName(name)
if sanitizedName == "" {
output.PrintError("HAT_INVALID_NAME", "Invalid hat name: must be lowercase alphanumeric with hyphens only")
return 2
}
// 2. Parse JSON config
var config HatConfig
if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
output.PrintError("HAT_INVALID_CONFIG", fmt.Sprintf("Invalid JSON config: %s", err.Error()))
return 2
}
// 3. Validate required fields
if err := validateHatConfig(&config); err != nil {
output.PrintError("HAT_INVALID_CONFIG", err.Error())
return 2
}
// Use sanitized name
config.Name = sanitizedName
// Set default icon if not provided
if config.Icon == "" {
config.Icon = "◇"
}
// 4. Find treehouse (validates we're in an initialized repo)
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.Treehousecmd.sanitizeHatName function · go · L142-L165 (24 LOC)internal/cmd/hat.go
func sanitizeHatName(name string) string {
// Convert to lowercase
name = strings.ToLower(name)
// Replace spaces with hyphens
name = strings.ReplaceAll(name, " ", "-")
// Remove any character that isn't alphanumeric or hyphen
var result strings.Builder
for _, r := range name {
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
result.WriteRune(r)
}
}
// Collapse multiple hyphens and trim
sanitized := result.String()
for strings.Contains(sanitized, "--") {
sanitized = strings.ReplaceAll(sanitized, "--", "-")
}
sanitized = strings.Trim(sanitized, "-")
return sanitized
}cmd.validateHatConfig function · go · L168-L173 (6 LOC)internal/cmd/hat.go
func validateHatConfig(config *HatConfig) error {
if config.Title == "" {
return fmt.Errorf("missing required field: title")
}
return nil
}cmd.createHatFile function · go · L176-L207 (32 LOC)internal/cmd/hat.go
func createHatFile(treehousePath, name string, config *HatConfig) error {
hatsDir := filepath.Join(treehousePath, "hats")
// Ensure hats directory exists
if err := os.MkdirAll(hatsDir, 0755); err != nil {
return err
}
titleCaser := cases.Title(language.English)
displayName := titleCaser.String(strings.ReplaceAll(config.Name, "-", " "))
if config.Name == "" {
displayName = "Hat"
}
hatMD := fmt.Sprintf(`# %s %s
> %s
---
## Domain Knowledge
(Add domain expertise that applies across all nooks)
---
Last Updated: (auto-updated on save)
`, config.Icon, displayName, config.Title)
hatPath := filepath.Join(hatsDir, name+".md")
return os.WriteFile(hatPath, []byte(hatMD), 0644)
}cmd.createHatCommandStub function · go · L210-L237 (28 LOC)internal/cmd/hat.go
func createHatCommandStub(repoRoot, name, title, icon string) (string, error) {
// Create directory structure
commandDir := filepath.Join(repoRoot, ".claude", "commands", "th", "hats")
if err := os.MkdirAll(commandDir, 0755); err != nil {
return "", err
}
titleCaser := cases.Title(language.English)
displayName := titleCaser.String(strings.ReplaceAll(name, "-", " "))
commandMD := fmt.Sprintf(`# %s %s
%s
TREEHOUSE_BASE_WORKSPACE=%s
<hat-loader>
1. Load {BASE_PATH}/.treehouse/hats/%s.md for domain knowledge
</hat-loader>
`, icon, displayName, title, repoRoot, name)
commandPath := filepath.Join(commandDir, name+".md")
if err := os.WriteFile(commandPath, []byte(commandMD), 0644); err != nil {
return "", err
}
return commandPath, nil
}cmd.runInit function · go · L34-L86 (53 LOC)internal/cmd/init.go
func runInit() int {
// 1. Validate git repository
repoInfo, err := git.DetectRepo()
if err != nil {
gitErr, ok := err.(*git.GitError)
if ok {
output.PrintError(gitErr.Code, gitErr.Message)
return 3
}
output.PrintError("GIT_ERROR", err.Error())
return 3
}
// 2. Check git version
if err := git.CheckVersion(); err != nil {
gitErr, ok := err.(*git.GitError)
if ok {
output.PrintError(gitErr.Code, gitErr.Message)
return 3
}
output.PrintError("GIT_ERROR", err.Error())
return 3
}
// 3. Check if .treehouse already exists
treehousePath := filepath.Join(repoInfo.Root, ".treehouse")
if _, err := os.Stat(treehousePath); err == nil {
output.PrintError("INIT_ALREADY_EXISTS", "Treehouse already initialized")
return 1
}
// 4. Update .gitignore before creating structure
gitignoreUpdated, err := updateGitignore(repoInfo.Root)
if err != nil {
output.PrintError("INIT_GITIGNORE_FAILED", err.Error())
return 1
}
// 5. Create folder structure
createcmd.createTreehouseStructure function · go · L90-L143 (54 LOC)internal/cmd/init.go
func createTreehouseStructure(basePath string) ([]string, error) {
created := []string{}
// Create directories
dirs := []string{
basePath,
filepath.Join(basePath, "nooks"),
filepath.Join(basePath, "hats"),
filepath.Join(basePath, "workflows"),
}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
// Cleanup on failure
_ = os.RemoveAll(basePath)
return nil, err
}
}
// Create decks.yaml
decksPath := filepath.Join(basePath, "decks.yaml")
if err := os.WriteFile(decksPath, []byte("decks: {}\n"), 0644); err != nil {
_ = os.RemoveAll(basePath)
return nil, err
}
created = append(created, "decks.yaml")
created = append(created, "nooks/")
created = append(created, "hats/")
// Install workflows from embedded assets
workflowsPath := filepath.Join(basePath, "workflows")
installedWorkflows, err := installWorkflows(workflowsPath)
if err != nil {
_ = os.RemoveAll(basePath)
return nil, err
}
for _, w := range installedWorkflows {Want this analysis on your repo? https://repobility.com/scan/
cmd.installWorkflows function · go · L146-L176 (31 LOC)internal/cmd/init.go
func installWorkflows(destPath string) ([]string, error) {
installed := []string{}
// Read workflow files from embedded assets
entries, err := assets.Workflows.ReadDir("workflows")
if err != nil {
return nil, err
}
for _, entry := range entries {
if entry.IsDir() {
continue // Skip claude/ subdirectory, handled separately
}
if filepath.Ext(entry.Name()) != ".md" {
continue
}
content, err := assets.Workflows.ReadFile("workflows/" + entry.Name())
if err != nil {
return nil, err
}
destFile := filepath.Join(destPath, entry.Name())
if err := os.WriteFile(destFile, content, 0644); err != nil {
return nil, err
}
installed = append(installed, entry.Name())
}
return installed, nil
}cmd.installClaudeCommands function · go · L180-L216 (37 LOC)internal/cmd/init.go
func installClaudeCommands(destPath string, repoRoot string) ([]string, error) {
installed := []string{}
// Create directory structure
if err := os.MkdirAll(destPath, 0755); err != nil {
return nil, err
}
// Read Claude command files from embedded assets
entries, err := assets.Workflows.ReadDir("workflows/claude")
if err != nil {
return nil, err
}
for _, entry := range entries {
if entry.IsDir() || filepath.Ext(entry.Name()) != ".md" {
continue
}
content, err := assets.Workflows.ReadFile("workflows/claude/" + entry.Name())
if err != nil {
return nil, err
}
// Replace placeholder with actual repoRoot path
contentStr := string(content)
contentStr = strings.Replace(contentStr, "{{TREEHOUSE_BASE_WORKSPACE}}", repoRoot, -1)
destFile := filepath.Join(destPath, entry.Name())
if err := os.WriteFile(destFile, []byte(contentStr), 0644); err != nil {
return nil, err
}
installed = append(installed, entry.Name())
}
return installed, nil
}cmd.updateGitignore function · go · L229-L262 (34 LOC)internal/cmd/init.go
func updateGitignore(repoRoot string) (bool, error) {
gitignorePath := filepath.Join(repoRoot, ".gitignore")
// Check if .gitignore exists
content, err := os.ReadFile(gitignorePath)
if err != nil {
if os.IsNotExist(err) {
// Create new .gitignore with our block
if err := os.WriteFile(gitignorePath, []byte(treehouseGitignoreBlock), 0644); err != nil {
return false, err
}
return true, nil
}
return false, err
}
// Check if treehouse entries already exist
if containsTreehouseEntries(string(content)) {
return false, nil // Already present, no update needed
}
// Append treehouse block to existing content
newContent := string(content)
if len(newContent) > 0 && newContent[len(newContent)-1] != '\n' {
newContent += "\n"
}
newContent += "\n" + treehouseGitignoreBlock
if err := os.WriteFile(gitignorePath, []byte(newContent), 0644); err != nil {
return false, err
}
return true, nil
}cmd.containsTreehouseEntries function · go · L265-L275 (11 LOC)internal/cmd/init.go
func containsTreehouseEntries(content string) bool {
// Check for the managed marker or the actual entries
if strings.Contains(content, treehouseGitignoreMarker) {
return true
}
// Also check for the individual entries in case added manually
if strings.Contains(content, ".treehouse/") && strings.Contains(content, ".claude/commands/th") {
return true
}
return false
}cmd.runList function · go · L65-L130 (66 LOC)internal/cmd/list.go
func runList() int {
// 1. Find treehouse (validates we're in an initialized repo)
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 2. Load decks
decksData, err := deck.LoadDecks(thInfo.TreehousePath)
if err != nil {
output.PrintError("DECK_LOAD_ERROR", err.Error())
return 1
}
// 3. Get base repository information
repoInfo, err := git.DetectRepo()
if err != nil {
gitErr, ok := err.(*git.GitError)
if ok {
output.PrintError(gitErr.Code, gitErr.Message)
return 3
}
output.PrintError("GIT_ERROR", err.Error())
return 3
}
baseInfo := BaseInfo{
Path: thInfo.RepoRoot,
Branch: repoInfo.Branch,
Commit: repoInfo.CommitSHA, // Already short form (7 chars)
}
// 4. Determine current nook
parentInfo, err := worktree.GetParentInfo(thInfo.TreehousePath)
if errcmd.buildDeckResults function · go · L133-L169 (37 LOC)internal/cmd/list.go
func buildDeckResults(decksData *deck.DecksFile, thInfo *treehouse.Info, currentNook *string) []DeckResult {
if decksData == nil || len(decksData.Decks) == 0 {
return []DeckResult{}
}
results := make([]DeckResult, 0, len(decksData.Decks))
for deckID, deckData := range decksData.Decks {
deckResult := DeckResult{
ID: deckID,
Created: deckData.Created,
Nooks: make([]NookResult, 0, len(deckData.Nooks)),
}
for nookID, nookData := range deckData.Nooks {
// Build worktree path
worktreePath := filepath.Join(thInfo.WorktreesPath, nookID)
// Determine status
status := determineNookStatus(nookID, worktreePath, currentNook)
nookResult := NookResult{
ID: nookID,
Parent: nookData.Parent,
Created: nookData.Created,
Worktree: worktreePath,
Status: status,
}
deckResult.Nooks = append(deckResult.Nooks, nookResult)
}
results = append(results, deckResult)
}
return results
}cmd.determineNookStatus function · go · L172-L185 (14 LOC)internal/cmd/list.go
func determineNookStatus(nookID string, worktreePath string, currentNook *string) string {
// Check if this is the current nook
if currentNook != nil && *currentNook == nookID {
return "active"
}
// Check if worktree exists
exists, err := worktree.Exists(worktreePath)
if err != nil || !exists {
return "orphan"
}
return "inactive"
}cmd.runPin function · go · L42-L106 (65 LOC)internal/cmd/pin.go
func runPin(content string) int {
// 1. Find treehouse (validates we're in an initialized repo)
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 2. Get current nook context
parentInfo, err := worktree.GetParentInfo(thInfo.TreehousePath)
if err != nil {
output.PrintError("PIN_NOT_IN_NOOK", "Must be in a nook to pin")
return 1
}
// 3. Verify we're in a nook
if !parentInfo.IsNook {
output.PrintError("PIN_NOT_IN_NOOK", "Must be in a nook to pin")
return 1
}
nookID := parentInfo.CurrentNook
// 4. Build nooks path and load boards
nooksPath := filepath.Join(thInfo.TreehousePath, "nooks")
boards, err := board.LoadBoards(nooksPath)
if err != nil {
boardErr, ok := err.(*board.BoardError)
if ok {
output.PrintError(boardErr.Code, boardErr.Message)
} else {
outputRepobility (the analyzer behind this table) · https://repobility.com
cmd.runPrune function · go · L42-L144 (103 LOC)internal/cmd/prune.go
func runPrune() int {
// 1. Find treehouse
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 2. Load decks
decks, err := deck.LoadDecks(thInfo.TreehousePath)
if err != nil {
deckErr, ok := err.(*deck.DeckError)
if ok {
// If no decks file, nothing to prune
if deckErr.Code == "DECK_FILE_NOT_FOUND" {
output.PrintSuccess(PruneResult{
Pruned: []string{},
DecksRemoved: []string{},
})
return 0
}
output.PrintError(deckErr.Code, deckErr.Message)
} else {
output.PrintError("DECK_ERROR", err.Error())
}
return 1
}
// 3. Find orphaned nooks (entries in decks.yaml with missing worktrees)
var orphans []string
for _, d := range decks.Decks {
if d.Nooks == nil {
continue
}
for nookID := range d.Nooks {
worktreePath := filepath.Joicmd.runRemove function · go · L49-L153 (105 LOC)internal/cmd/remove.go
func runRemove(nookID string) int {
// 0. Validate nook ID format (prevents path traversal)
if err := nook.ValidateNookID(nookID); err != nil {
nookErr, ok := err.(*nook.NookError)
if ok {
output.PrintError(nookErr.Code, nookErr.Message)
} else {
output.PrintError("INVALID_NOOK_ID", err.Error())
}
return 2
}
// 1. Find treehouse
thInfo, err := treehouse.FindTreehouse(".")
if err != nil {
thErr, ok := err.(*treehouse.TreehouseError)
if ok {
output.PrintError(thErr.Code, thErr.Message)
} else {
output.PrintError("INIT_NOT_FOUND", err.Error())
}
return 1
}
// 2. Check if trying to remove current nook
parentInfo, err := worktree.GetParentInfo(thInfo.TreehousePath)
if err != nil {
wtErr, ok := err.(*worktree.WorktreeError)
if ok {
output.PrintError(wtErr.Code, wtErr.Message)
return 1
}
output.PrintError("WORKTREE_ERROR", err.Error())
return 1
}
if parentInfo.IsNook && parentInfo.CurrentNook == nookID {
output.PrintError("NOOK_cmd.collectNooksToRemoveWithDepth function · go · L161-L182 (22 LOC)internal/cmd/remove.go
func collectNooksToRemoveWithDepth(decks *deck.DecksFile, nookID string, depth int) []string {
// Prevent stack overflow with depth limit
if depth >= maxRecursionDepth {
// Return just this nook if we hit the limit
return []string{nookID}
}
var result []string
// Get direct children
children := deck.GetChildNooks(decks, nookID)
// Recursively collect all descendants (depth-first)
for _, child := range children {
result = append(result, collectNooksToRemoveWithDepth(decks, child, depth+1)...)
}
// Add this nook last (after all children)
result = append(result, nookID)
return result
}cmd.init function · go · L43-L49 (7 LOC)internal/cmd/root.go
func init() {
rootCmd.Flags().BoolVarP(&versionFlag, "version", "v", false, "Print version information")
// Disable default help flag - we output JSON for everything
rootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
output.PrintError("NO_COMMAND", "No command specified. Use a subcommand.")
})
}cmd.Execute function · go · L53-L119 (67 LOC)internal/cmd/root.go
func Execute(args []string) int {
// Reset version flag and exit codes for each execution (important for tests)
versionFlag = false
initExitCode = 0
listExitCode = 0
removeExitCode = 0
pruneExitCode = 0
hatExitCode = 0
pinExitCode = 0
boardExitCode = 0
rootCmd.SetArgs(args)
err := rootCmd.Execute()
if err != nil {
// Handle unknown flags and other parsing errors
output.PrintError("INVALID_ARGS", err.Error())
return 2
}
// If version was requested, return success
if versionFlag {
return 0
}
// If no args provided (no subcommand), return exit code 2
if len(args) == 0 {
return 2
}
// Check if init command was executed and return its exit code
if len(args) > 0 && args[0] == "init" {
return initExitCode
}
// Check if list command was executed and return its exit code
if len(args) > 0 && args[0] == "list" {
return listExitCode
}
// Check if remove command was executed and return its exit code
if len(args) > 0 && args[0] == "remove" {
return rdeck.LoadDecks function · go · L39-L70 (32 LOC)internal/deck/deck.go
func LoadDecks(treehousePath string) (*DecksFile, error) {
decksPath := filepath.Join(treehousePath, "decks.yaml")
data, err := os.ReadFile(decksPath)
if err != nil {
if os.IsNotExist(err) {
return nil, &DeckError{
Code: "DECK_FILE_NOT_FOUND",
Message: fmt.Sprintf("decks.yaml not found at %s", decksPath),
}
}
return nil, &DeckError{
Code: "DECK_READ_FAILED",
Message: fmt.Sprintf("Failed to read decks.yaml: %v", err),
}
}
var decksFile DecksFile
if err := yaml.Unmarshal(data, &decksFile); err != nil {
return nil, &DeckError{
Code: "DECK_PARSE_FAILED",
Message: fmt.Sprintf("Failed to parse decks.yaml: %v", err),
}
}
// Initialize empty maps if nil
if decksFile.Decks == nil {
decksFile.Decks = make(map[string]*Deck)
}
return &decksFile, nil
}deck.NookExists function · go · L73-L92 (20 LOC)internal/deck/deck.go
func NookExists(treehousePath string, nookID string) (bool, error) {
decks, err := LoadDecks(treehousePath)
if err != nil {
// If decks.yaml doesn't exist, no nooks exist
if deckErr, ok := err.(*DeckError); ok && deckErr.Code == "DECK_FILE_NOT_FOUND" {
return false, nil
}
return false, err
}
for _, deck := range decks.Decks {
if deck.Nooks != nil {
if _, exists := deck.Nooks[nookID]; exists {
return true, nil
}
}
}
return false, nil
}deck.GetNook function · go · L95-L113 (19 LOC)internal/deck/deck.go
func GetNook(treehousePath string, nookID string) (*Nook, string, error) {
decks, err := LoadDecks(treehousePath)
if err != nil {
return nil, "", err
}
for deckID, deck := range decks.Decks {
if deck.Nooks != nil {
if nook, exists := deck.Nooks[nookID]; exists {
return nook, deckID, nil
}
}
}
return nil, "", &DeckError{
Code: "NOOK_NOT_FOUND",
Message: fmt.Sprintf("Nook '%s' not found", nookID),
}
}All rows above produced by Repobility · https://repobility.com
deck.SaveDecks function · go · L116-L183 (68 LOC)internal/deck/deck.go
func SaveDecks(treehousePath string, decks *DecksFile) error {
decksPath := filepath.Join(treehousePath, "decks.yaml")
// Marshal to YAML
data, err := yaml.Marshal(decks)
if err != nil {
return &DeckError{
Code: "DECK_MARSHAL_FAILED",
Message: fmt.Sprintf("Failed to marshal decks: %v", err),
}
}
// Create temp file in same directory for atomic rename
tempFile, err := os.CreateTemp(treehousePath, "decks.yaml.tmp.*")
if err != nil {
return &DeckError{
Code: "DECK_WRITE_FAILED",
Message: fmt.Sprintf("Failed to create temp file: %v", err),
}
}
tempPath := tempFile.Name()
// Ensure temp file cleanup on error
defer func() {
if tempPath != "" {
os.Remove(tempPath)
}
}()
// Write data to temp file
if _, err := tempFile.Write(data); err != nil {
tempFile.Close()
return &DeckError{
Code: "DECK_WRITE_FAILED",
Message: fmt.Sprintf("Failed to write temp file: %v", err),
}
}
// Sync to disk
if err := tempFile.Sync(); err != nil {deck.CreateDeck function · go · L192-L197 (6 LOC)internal/deck/deck.go
func CreateDeck(deckID string, created string) *Deck {
return &Deck{
Created: created,
Nooks: make(map[string]*Nook),
}
}deck.AddNookToDeck function · go · L201-L226 (26 LOC)internal/deck/deck.go
func AddNookToDeck(decks *DecksFile, deckID string, nookID string, parent string, created string) string {
// Initialize decks map if nil
if decks.Decks == nil {
decks.Decks = make(map[string]*Deck)
}
// Create deck if it doesn't exist
deck, exists := decks.Decks[deckID]
if !exists {
deck = CreateDeck(deckID, created)
decks.Decks[deckID] = deck
}
// Initialize nooks map if nil
if deck.Nooks == nil {
deck.Nooks = make(map[string]*Nook)
}
// Add the nook
deck.Nooks[nookID] = &Nook{
Parent: parent,
Created: created,
}
return deckID
}deck.RemoveNook function · go · L230-L252 (23 LOC)internal/deck/deck.go
func RemoveNook(decks *DecksFile, deckID string, nookID string) (bool, error) {
deck, exists := decks.Decks[deckID]
if !exists {
return false, &DeckError{
Code: "DECK_NOT_FOUND",
Message: fmt.Sprintf("Deck '%s' not found", deckID),
}
}
if deck.Nooks == nil {
return true, nil
}
delete(deck.Nooks, nookID)
// Check if deck is now empty
if len(deck.Nooks) == 0 {
delete(decks.Decks, deckID)
return true, nil
}
return false, nil
}deck.GetDeckForNook function · go · L255-L264 (10 LOC)internal/deck/deck.go
func GetDeckForNook(decks *DecksFile, nookID string) (string, bool) {
for deckID, deck := range decks.Decks {
if deck.Nooks != nil {
if _, exists := deck.Nooks[nookID]; exists {
return deckID, true
}
}
}
return "", false
}deck.GetChildNooks function · go · L267-L279 (13 LOC)internal/deck/deck.go
func GetChildNooks(decks *DecksFile, parentNookID string) []string {
var children []string
for _, deck := range decks.Decks {
if deck.Nooks != nil {
for nookID, nook := range deck.Nooks {
if nook.Parent == parentNookID {
children = append(children, nookID)
}
}
}
}
return children
}git.DetectRepo function · go · L41-L74 (34 LOC)internal/git/detect.go
func DetectRepo() (*RepoInfo, error) {
// Check if inside git repo and get root
rootOut, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
if err != nil {
return nil, &GitError{
Code: "INIT_NOT_GIT_REPO",
Message: "Not a git repository",
}
}
// Get current branch
branchOut, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output()
if err != nil {
return nil, &GitError{
Code: "GIT_BRANCH_ERROR",
Message: fmt.Sprintf("Failed to get branch: %v", err),
}
}
// Get commit SHA (first 7 characters)
shaOut, err := exec.Command("git", "rev-parse", "--short=7", "HEAD").Output()
if err != nil {
return nil, &GitError{
Code: "GIT_SHA_ERROR",
Message: fmt.Sprintf("Failed to get commit SHA: %v", err),
}
}
return &RepoInfo{
Root: strings.TrimSpace(string(rootOut)),
Branch: strings.TrimSpace(string(branchOut)),
CommitSHA: strings.TrimSpace(string(shaOut)),
}, nil
}git.CheckVersion function · go · L79-L97 (19 LOC)internal/git/detect.go
func CheckVersion() error {
output, err := exec.Command("git", "--version").Output()
if err != nil {
return &GitError{
Code: "GIT_NOT_FOUND",
Message: "Git not installed",
}
}
version, err := parseVersion(string(output))
if err != nil {
return &GitError{
Code: "GIT_VERSION_PARSE_ERROR",
Message: fmt.Sprintf("Failed to parse git version: %v", err),
}
}
return checkVersionRequirement(version)
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
git.parseVersion function · go · L101-L129 (29 LOC)internal/git/detect.go
func parseVersion(versionStr string) (Version, error) {
// Use pre-compiled regex with optional patch version
matches := versionRegex.FindStringSubmatch(versionStr)
if len(matches) < 3 {
return Version{}, fmt.Errorf("invalid git version format: %s", versionStr)
}
major, err := strconv.Atoi(matches[1])
if err != nil {
return Version{}, fmt.Errorf("invalid major version: %v", err)
}
minor, err := strconv.Atoi(matches[2])
if err != nil {
return Version{}, fmt.Errorf("invalid minor version: %v", err)
}
// Patch is optional (some git versions report only major.minor)
var patch int
if len(matches) > 3 && matches[3] != "" {
patch, err = strconv.Atoi(matches[3])
if err != nil {
return Version{}, fmt.Errorf("invalid patch version: %v", err)
}
}
return Version{Major: major, Minor: minor, Patch: patch}, nil
}git.checkVersionRequirement function · go · L132-L141 (10 LOC)internal/git/detect.go
func checkVersionRequirement(v Version) error {
// Git 2.5+ is required for worktree support
if v.Major < 2 || (v.Major == 2 && v.Minor < 5) {
return &GitError{
Code: "GIT_VERSION_UNSUPPORTED",
Message: "Git 2.5+ required for worktree support",
}
}
return nil
}nook.GenerateID function · go · L30-L48 (19 LOC)internal/nook/nook.go
func GenerateID(name string, commitSHA string) (string, error) {
if len(commitSHA) < 4 {
return "", &NookError{
Code: "NOOK_INVALID_SHA",
Message: "Commit SHA must be at least 4 characters",
}
}
sanitized := SanitizeName(name)
if sanitized == "" {
return "", &NookError{
Code: "NOOK_NAME_INVALID",
Message: "Nook name cannot be empty or contain only special characters",
}
}
hash := strings.ToLower(commitSHA[:4])
return fmt.Sprintf("%s-%s", hash, sanitized), nil
}nook.SanitizeName function · go · L57-L74 (18 LOC)internal/nook/nook.go
func SanitizeName(name string) string {
// Step 1: Convert to lowercase
result := strings.ToLower(name)
// Step 2: Replace spaces with hyphens
result = strings.ReplaceAll(result, " ", "-")
// Step 3: Remove non-alphanumeric characters (except hyphens)
result = nonAlphanumericRegex.ReplaceAllString(result, "")
// Step 4: Collapse multiple consecutive hyphens
result = multipleHyphensRegex.ReplaceAllString(result, "-")
// Step 5: Trim leading/trailing hyphens
result = strings.Trim(result, "-")
return result
}nook.ValidateName function · go · L77-L86 (10 LOC)internal/nook/nook.go
func ValidateName(name string) error {
sanitized := SanitizeName(name)
if sanitized == "" {
return &NookError{
Code: "NOOK_NAME_INVALID",
Message: "Nook name cannot be empty or contain only special characters",
}
}
return nil
}nook.ParseNookID function · go · L90-L117 (28 LOC)internal/nook/nook.go
func ParseNookID(nookID string) (hash string, name string, err error) {
if len(nookID) < 6 { // minimum: 4-char hash + hyphen + 1-char name
return "", "", &NookError{
Code: "NOOK_ID_INVALID",
Message: fmt.Sprintf("Invalid nook ID format: %s", nookID),
}
}
// Find the first hyphen after the 4-char hash
if nookID[4] != '-' {
return "", "", &NookError{
Code: "NOOK_ID_INVALID",
Message: fmt.Sprintf("Invalid nook ID format: %s", nookID),
}
}
hash = nookID[:4]
name = nookID[5:]
if name == "" {
return "", "", &NookError{
Code: "NOOK_ID_INVALID",
Message: fmt.Sprintf("Invalid nook ID format: %s", nookID),
}
}
return hash, name, nil
}nook.ValidateNookID function · go · L124-L150 (27 LOC)internal/nook/nook.go
func ValidateNookID(nookID string) error {
// Check minimum length
if len(nookID) < 6 {
return &NookError{
Code: "INVALID_NOOK_ID",
Message: fmt.Sprintf("Invalid nook ID format: %s", nookID),
}
}
// Check for path traversal attempts
if strings.Contains(nookID, "..") || strings.Contains(nookID, "/") || strings.Contains(nookID, "\\") {
return &NookError{
Code: "INVALID_NOOK_ID",
Message: fmt.Sprintf("Invalid nook ID: contains illegal characters: %s", nookID),
}
}
// Validate format with regex
if !nookIDRegex.MatchString(nookID) {
return &NookError{
Code: "INVALID_NOOK_ID",
Message: fmt.Sprintf("Invalid nook ID format: %s", nookID),
}
}
return nil
}output.PrintError function · go · L38-L44 (7 LOC)internal/output/json.go
func PrintError(code, message string) {
resp := Response{
Success: false,
Error: &ErrorInfo{Code: code, Message: message},
}
printJSON(resp)
}Want this analysis on your repo? https://repobility.com/scan/
output.printJSON function · go · L47-L54 (8 LOC)internal/output/json.go
func printJSON(v interface{}) {
bytes, err := json.Marshal(v)
if err != nil {
// Fallback to a valid error JSON if marshal fails
bytes = []byte(`{"success":false,"error":{"code":"MARSHAL_ERROR","message":"failed to marshal response"}}`)
}
fmt.Fprintln(writer, string(bytes))
}testutil.SetupGitRepo function · go · L13-L56 (44 LOC)internal/testutil/git.go
func SetupGitRepo(t *testing.T) string {
t.Helper()
dir := t.TempDir()
// Initialize git repo
cmd := exec.Command("git", "init")
cmd.Dir = dir
if err := cmd.Run(); err != nil {
t.Fatalf("failed to init git repo: %v", err)
}
// Configure git user for commits
cmd = exec.Command("git", "config", "user.email", "[email protected]")
cmd.Dir = dir
if err := cmd.Run(); err != nil {
t.Fatalf("failed to config git email: %v", err)
}
cmd = exec.Command("git", "config", "user.name", "Test User")
cmd.Dir = dir
if err := cmd.Run(); err != nil {
t.Fatalf("failed to config git name: %v", err)
}
// Create initial commit so HEAD exists
testFile := filepath.Join(dir, "test.txt")
if err := os.WriteFile(testFile, []byte("test"), 0644); err != nil {
t.Fatalf("failed to create test file: %v", err)
}
cmd = exec.Command("git", "add", ".")
cmd.Dir = dir
if err := cmd.Run(); err != nil {
t.Fatalf("failed to git add: %v", err)
}
cmd = exec.Command("git", "commit", "-m", "inititestutil.ChdirWithCleanup function · go · L60-L71 (12 LOC)internal/testutil/git.go
func ChdirWithCleanup(t *testing.T, dir string) {
t.Helper()
oldWd, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %v", err)
}
t.Cleanup(func() { _ = os.Chdir(oldWd) })
if err := os.Chdir(dir); err != nil {
t.Fatalf("failed to change to directory %s: %v", dir, err)
}
}page 1 / 2next ›