Layr-Labs / Layr-Labs/devkit-cli

Command Guardrails for handling out of sequence cli commands and context aware error messages

Open
#117 6 comments 0 reactions 1 assignee View on GitHub

@supernovahs is already working on this.

Since May 21, 2025.

enhancement
Dominant language
Go
Stars
27
Forks
10
PR merge metrics
No merged PRs in 30d

Description

Command Flow Guardrails: Dependency Management for CLI Commands

Overview

Command Flow Guardrails detect when CLI commands are run out of expected sequence and provide context-aware error messages to guide users. This feature ensures commands like avs call (which depends on avs contract-deploy) fail gracefully with helpful guidance.

Key Components

  1. Command Dependency Definitions: Map of commands to their prerequisites
  2. Command History Tracking: In-memory registry of executed commands
  3. Dependency Checking Middleware: Validates dependencies before execution
  4. Contextual Error Messages: Guides users to the correct next actions

Implementation

1. Command Dependency Definition
// CommandDependency defines a command dependency relationship
type CommandDependency struct {
    Command       string     // Command that has dependencies
    DependsOn     []string   // Commands that must be run before this command
    ErrorMessage  string     // Helpful message when dependency isn't met
    CheckFunc     func() bool // Optional additional validation
}

// Sample dependencies
var CommandFlowDependencies = []CommandDependency{
    {
        Command:   "call",
        DependsOn: []string{"deploy-contracts"},
        ErrorMessage: "The 'avs call' command requires contract deployment. " +
            "Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.",
        CheckFunc: checkContractsDeployed,
    },
    // Other dependencies...
}
2. Command Execution Tracking
// Track command execution history
var commandHistory = struct {
    executedCommands map[string]bool
    mu               sync.Mutex
}{
    executedCommands: make(map[string]bool),
}

// Record successful command execution
func recordCommandExecution(command string) {
    commandHistory.mu.Lock()
    defer commandHistory.mu.Unlock()
    commandHistory.executedCommands[command] = true
}
3. Dependency Checking Middleware
// Middleware that enforces command dependencies
func WithCommandDependencyCheck(action cli.ActionFunc) cli.ActionFunc {
    return func(ctx *cli.Context) error {
        cmdName := ctx.Command.Name
        
        // Skip checks for create command (entry point) 
        if cmdName == "create" {
            result := action(ctx)
            if result == nil {
                recordCommandExecution(cmdName)
            }
            return result
        }

        // Check dependencies
        for _, dep := range CommandFlowDependencies {
            if dep.Command == cmdName {
                for _, depCmd := range dep.DependsOn {
                    if !hasCommandBeenExecuted(depCmd) && 
                       !(dep.CheckFunc != nil && dep.CheckFunc()) {
                        return errors.New(dep.ErrorMessage)
                    }
                }
            }
        }

        // Execute command and record success
        result := action(ctx)
        if result == nil {
            recordCommandExecution(cmdName)
        }
        return result
    }
}
4. Integration with CLI Framework
func main() {
    
    actionChain := hooks.NewActionChain()
    actionChain.Use(WithCommandDependencyCheck)

    
    hooks.ApplyMiddleware(app.Commands, actionChain)
    
}

User Experience

When a user attempts to run a command before its prerequisites:

$ devkit avs call  signature="(uint256)" args="(5)"

Error: The 'avs call' command requires contract deployment. 
Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.
  • Users receive clear error message about the correct command sequence and next steps.

Additional Validations

For complex dependencies that can't be verified by simple command history:

// Validation function example
func checkContractsDeployed() bool {
    // Check for config files with deployed contract addresses
    contextPath := filepath.Join("config", "contexts", "devnet.yaml")
    if _, err := os.Stat(contextPath); os.IsNotExist(err) {
        return false
    }
    
    // Parse YAML and verify contract addresses exist
    // [Implementation details...]
    
    return contractsExist
}

Open questions

  • Is there any check that should be made for create command ?

Example validations

  • Check that fork url is set before devnet start is called in the context file

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.