Skip to content

feat(nushell): add Nushell plugin support#59

Open
lacymorrow wants to merge 2 commits into
mainfrom
LAC-1302/nushell-support
Open

feat(nushell): add Nushell plugin support#59
lacymorrow wants to merge 2 commits into
mainfrom
LAC-1302/nushell-support

Conversation

@lacymorrow

Copy link
Copy Markdown
Owner

Summary

Closes #38. Adds Nushell support following the same structure as the Fish plugin (lacy.plugin.fish + lib/fish/).

  • lacy.plugin.nu — entry point; source from ~/.config/nushell/config.nu
  • lib/nu/config.nu — globals, agent words, config.yaml loader
  • lib/nu/detection.nu_lacy_classify_input (uses which instead of command -v)
  • lib/nu/execute.nu_lacy_query_agent, _lacy_send_to_agent, public lacy command
  • lib/nu/keybindings.nu — Alt+Enter (send to agent), Ctrl+Space (mode toggle)
  • lib/nu/prompt.nu — right-prompt mode badge (SHELL / AGENT / AUTO)

Nushell limitation: Enter cannot be seamlessly overridden without losing interactive shell state (Nushell has no equivalent to ZSH's zle accept-line or Fish's commandline -f execute). Instead, normal Enter executes as shell and Alt+Enter routes the buffer to the agent. The lacy "query" command is also available for explicit queries.

Requires Nushell 0.87+. Zero changes to existing files.

Test plan

  • source ~/.lacy/lacy.plugin.nu in ~/.config/nushell/config.nu
  • Right prompt shows AUTO badge
  • Ctrl+Space cycles through SHELL → AGENT → AUTO modes
  • Alt+Enter with a natural-language buffer routes to agent
  • lacy "why does this fail?" invokes the active AI tool
  • lacy without args prompts for input
  • Config from ~/.lacy/config.yaml is picked up (active tool, default mode)

Adds lacy.plugin.nu and lib/nu/{config,detection,execute,keybindings,prompt}.nu
following the same structure as the Fish plugin. Provides config loading,
input classification (via `which` instead of `command -v`), agent routing,
Alt+Enter keybinding to send buffer to agent, Ctrl+Space mode toggle, and
a right-prompt mode badge. Requires Nushell 0.87+.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a Nushell plugin for Lacy Shell, enabling AI agent integration. It includes modules for configuration, input classification, command execution routing, keybindings, and prompt customization. Feedback was provided regarding the manual YAML parsing in lib/nu/config.nu, recommending the use of Nushell's native 'from yaml' command to improve robustness and correctly handle nested structures.

Comment thread lib/nu/config.nu Outdated
Comment on lines +42 to +80
def _lacy_load_config [] {
let config_file = ($env.HOME | path join ".lacy" "config.yaml")
if not ($config_file | path exists) { return }

let file_lines = (open --raw $config_file | lines)

# Parse agent_tools.active
let active_lines = ($file_lines | where { |line| ($line | str trim | str starts-with "active:") })
if ($active_lines | length) > 0 {
let active = ($active_lines | first
| str replace -r '.*active:\s*' ''
| str trim
| str replace --all '"' ''
| str replace --all "'" '')
if $active != "" { $env.LACY_ACTIVE_TOOL = $active }
}

# Parse agent_tools.custom_command
let custom_lines = ($file_lines | where { |line| ($line | str trim | str starts-with "custom_command:") })
if ($custom_lines | length) > 0 {
let custom = ($custom_lines | first
| str replace -r '.*custom_command:\s*' ''
| str trim
| str replace --all '"' ''
| str replace --all "'" '')
if $custom != "" { $env.LACY_CUSTOM_TOOL_CMD = $custom }
}

# Parse modes.default
let mode_lines = ($file_lines | where { |line| ($line | str trim | str starts-with "default:") })
if ($mode_lines | length) > 0 {
let mode = ($mode_lines | first
| str replace -r '.*default:\s*' ''
| str trim
| str replace --all '"' ''
| str replace --all "'" '')
if $mode != "" { $env.LACY_SHELL_MODE = $mode }
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of _lacy_load_config manually parses the config.yaml file using string manipulation. This approach is fragile and can easily break if the YAML structure changes (e.g., with different indentation). It also doesn't correctly handle the nested structure of the configuration file (e.g. agent_tools.active), as it searches for keys like active: anywhere in the file.

Nushell provides built-in support for parsing YAML with the from yaml command. Using it would make the code much more robust, maintainable, and idiomatic.

Consider this refactoring, which uses from yaml to correctly parse the nested configuration and is resilient to formatting changes:

def _lacy_load_config [] {
    let config_file = ($env.HOME | path join ".lacy" "config.yaml")
    if not ($config_file | path exists) { return }

    try {
        let config = (open $config_file | from yaml)

        if ($config | get agent_tools.active?) != null {
            let active = ($config.agent_tools.active | default "" | str trim)
            if $active != "" { $env.LACY_ACTIVE_TOOL = $active }
        }

        if ($config | get agent_tools.custom_command?) != null {
            let custom = ($config.agent_tools.custom_command | default "" | str trim)
            if $custom != "" { $env.LACY_CUSTOM_TOOL_CMD = $custom }
        }

        if ($config | get modes.default?) != null {
            let mode = ($config.modes.default | default "" | str trim)
            if $mode != "" { $env.LACY_SHELL_MODE = $mode }
        }
    } catch {
        print --stderr "Lacy Shell: Error parsing ~/.lacy/config.yaml. Please check its format."
    }
}

…1302)

- Replace fragile line-by-line YAML string parsing with `from yaml`
  + `get --optional <path>` so nested keys (agent_tools.active vs modes.default)
  no longer collide and parsing survives indentation changes
- Mark `_lacy_load_config` and `_lacy_toggle_mode` as `def --env` so their
  $env mutations actually propagate to the caller — without it the config
  load and mode toggle silently no-op'd in real Nushell sessions
@lacymorrow

Copy link
Copy Markdown
Owner Author

CI green on c55f9ca: Syntax (bash) ✓, Syntax (zsh) ✓, shellcheck ✓. PR is MERGEABLE. Holding in_review for human merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Nushell support

2 participants