ROADMAP

September 25, 2025 · View on GitHub

High-level overview of the project’s goals, tasks, and milestones for future releases.

Any new ideas related to the content here are welcome.

Sections:

Current Prioritized Changes

  • abbr parser to build expandable CompletionItem snippets that insert the cursor in the abbr --set-cursor=% output.

    • Normal case without --set-cursor would just directly insert the abbr and add more CompletionItem.commitCharacters to these specific items.
    • Special case using --set-cursor would get the output of the abbr, and then replace the --set-cursor=% token with the snippet expansion token. Lots to consider here -- do we read this from a subshell? Performance could be a concern here if we do use a subshell.
  • Add code actions to replace absolute paths w/ variable that points to the previous location

    • inefficient path diagnostics (inefficient meaning, things like absolute paths that could be replaced with relative paths, or variables that point to the same location)
    • checking if a symbol is a path (could be isString(), isConcatenation(), ...). Currently considering a simple check for / in the node.text, to solve this
  • make __fish_contains_opt opt be considered as a argparse reference to the variable opt

    • __fish_contains_opt -s o opt would match the argparse o/opt definition in the matching function/completion file
    • complete -c cmd -n '__fish_contains_opt opt' would be a common usage
  • add support for hovering a ~/some/file/path and show the expanded result

    • add info diagnostics for replacing absolute paths with expandable paths
    • allow disabling this feature
  • add support for renaming ALL autoloaded files (currently requires atleast two code-actions to be used)

    • when a code-action changes an autoloaded function, also rename its completions file, and vice versa
  • Add virtual document support for go-to-definition of a manpage

  • Server Command to display fish_config in a browser

  • add headless mode for the server (allows for using the server via the commandline, without opening any client).

    • for example, fish-lsp headless --code-action='generate.completions' --file=~/.config/fish/functions/foo.fish would create a completions file for the foo.fish function, if it has an argparse in its body.
      • fish-lsp headless --show-tree --file=~/.config/fish/functions/foo.fish would show the client tree of the file
      • fish-lsp headless --get-references --file=~/.config/fish/functions/foo.fish --function=foo would show the references for the symbol defined in the file with the name foo
        • allow passing options for which scope to match the definition symbol, to search for specific references
          • --scope=local would only match references in the current file
          • --scope=global would match references in the current file and all files in the workspace
      • fish-lsp headless --show-tree --file=~/.config/fish/functions/foo.fish --scope=global would show all global symbols in the file
      • fish-lsp headless --get-references --file=~/.config/fish/functions/foo.fish --function=foo --scope=global would show all references to the symbol foo in the file and all files in the workspace
      • fish-lsp headless --diagnostics would show all diagnostics for the current workspace, or a specific file if passed with --file=~/.config/fish/functions/foo.fish
      • fish-lsp headless --workspace-symbols would show all symbols in the current workspace, or a specific file if passed with --file=~/.config/fish/functions/foo.fish
      • add completions for using the headless mode, so that the user does not have to remember how to use each subcommand
  • add support for a document to contain changes to the server's settings, and the server to update its settings based on the document changes

    • cli command to generate the default settings file with default values
    • cli command to show the current settings file of the directory $PWD
    • server command to create a new settings file in the current workspace
    • server command to update the server's settings file in the current workspace
    • server command to show the current server's settings file inside of the current workspace
    • create a schema for the server's settings file, so that a json-lsp client can validate the settings file and provide completions
    • allow the user to specify custom fish file paths in the current workspace that should be treated like they were autoloaded files
    • consider allowing converting the server's settings file to its equivalent fish source code
    • allow any code-action that uses # @fish-lsp-disable to also be specified in the server's settings file. (NEED TO THINK ABOUT BEST WAY TO STORE THIS)
  • allow function definitions with --no-scope-shadowing or other flags that would change how the caller's scope is used, to be recognized as references relative to the request position.

    function foo
        set -l baz 1
        #      ^^^---------- getReferences() to this variable [TOTAL: 2] (CASE 1)
        bar
        # since we call bar from the same scope as the getReferences() definition symbol
        # and bar has the `--no-scope-shadowing` flag, the reference to `baz` would be
        # considered a matching reference to the `baz` variable in the `foo` function
    end
    function bar --no-scope-shadowing
        echo $baz
        #     ^^^----------- getReferences() to this variable [TOTAL: 0] (CASE 2)
    end
    # Summary: 
    # 
    # When baz references are requested from inside the foo function,
    # we check all commands called inside of the foo function. if any of them
    # inherit the scope of the foo function, add the local references from the 
    # called function to the references of the foo function.
    #
    # 
    # When we check the references for `baz` inside of the `bar` function, we
    # only show references that are used inside of the `bar` function.
    

    NOTE: You could also try to find all references to the parent function and then add the caller scopes to the references of the parent function. This way, Case 2 would include the references to $baz in foo

  • allow functions with --argument-names to provide inlay hints for the arguments that are passed into the function calls, so that named arguments are shown in the client as inlay hints.

  • add support for expanding concatenation SyntaxNode: definitions, references and hovers

    for opt in fish_lsp_{enabled_handlers,disabled_handlers,commit_characters,log_file,log_level,all_indexed_paths,modifiable_paths,diagnostic_disable_error_codes,enable_experimental_diagnostics,max_background_files,show_client_popups,single_workspace_support}
    #          ^^^^^^^^^^---------------------- Hovering here would show the expansion 
        if not contains -- $opt $features_to_skip
            echo -e "$opt\t'fish-lsp env variable'"
        end
    end
    
  • Inline Value provider (debugger for current line of script)

  • Allow formatting of files without using fish_indent command

  • Write server handler for Call Hierarchy requests

  • Allow server to support registering a capability for the client to check the type -ap a command under the current location.

  • Support options to enable from client configuration

    • if_statement must be silent: if command -s -> if command -sq
    • prefer command _ prefix for ambiguous commands
    • default case for switch_statement
    • test number/string flags from condition argument's
    • function requires returning a status number
    • fish_add_path instead of set -gx PATH _
    • logger location
    • private functions need underscore prefix
    • prefer universal scope, or prefer global scope
    • prefer specific redirect to /dev/null
    • hover documentation fallback: tldr, cht.sh, ...
    • format specific options
    • remove showing lsp kind in completions list
  • Add server handler for onSemanticToken support

  • Add server handler for textDocument/publishDiagnostics to allow project wide diagnostics

  • Add code action to convert shebangs

    • #!/usr/bin/fish to #!/usr/bin/env fish
    • #!/usr/local/bin/fish to #!/usr/bin/env fish
  • add hover support to end stdin token --

  • add code-action to convert external shell commands to fish builtins (where applicable)

  • add fish-lsp info --time-startup --use-workspace $PWD support, to time how long it takes to start the server with only the current workspace

  • consider if exported variables should not be included in the unused FishSymbol[] reported by diagnostic 4004

General Codebase Changes

  • Add binary releases for common platforms
    • fish-lsp binary for macOS
    • fish-lsp binary for Linux
    • fish-lsp binary for Windows
  • Improve filtering of tokens between renaming and referencing (tricky issue because the lsif.dev specification does not support renaming symbols that don't have exact matching names
    • argparse h/help vs $_flag_{h,help} vs set -lq _flag_help vs complete -s h -l help vs cmd --help/cmd -h
    • set -gx fish_lsp_* vs $_fish_lsp_{var_name}
    • alias foo='bar' vs foo vs function foo --wraps=bar;...end;
    • function baz --wraps=foo vs foo vs function foo; end;
    • complete -n 'foo' ... vs function foo; end;
    • bind ... foo vs bind ... 'foo' vs function foo; end;
    • abbr ... --function foo vs function foo; end; vs abbr ... foo
  • update src/references.ts w/ a getReferences() function that supports passing general behavior changes
  • Add $__fish_** auto-loaded environment variables to the server's startup configuration. An example auto-loaded variable would be $__fish_config_dir
  • Improve parsing of specific DocumentSymbols (now FishSymbol) by using more verbose rules for excluding certain tokens from web-tree-sitter
  • Add better workspace support for non-standard/small fish workspaces. THE server FILE LIKELY NEEDS workspace handlers
    • Supporting /tmp/*.fish buffers from things like edit_command_buffer/alt-e
    • Supporting fisher workspaces (consider a workspace like ~/repo/fisher-plugin, as its own workspace without $fish_lps_all_indexed_paths)

      NOTE: fish_lsp_single_workspace_support was an attempt at specifying that the user has opted into this feature

    • Supporting sourced files outside of workspace, and adding them to the workspace
  • Go-to-Definition && Hover support for source some_file.fish command
  • Improving completions for set -gx fish_lsp_* env variables
    • adding better hover documentation to fish_lsp_* env variables, using the options property
  • Comparing already generated complete -c cmd -s _ -l _ completions to the a function with an argparse child definition, so that duplicate completions are not generated
    • argparse 'n/name=' -- $argv command could generate complete -c cmd -s n -l name -a ' ' - Key difference being the -a flag is outputted There is also the -x and -r flags that could be used.
  • General plumbing
    • Add more test coverage for heavily used files.
    • Remove unused/deprecated files and/or functions
  • Consider allowing the user to specify configuring the fish_indent command behavior
    • fish v3.7.1 to fish v4.0.0 changes fish_indent behavior specifically for ; characters to be replaced with \n, creating potentially unwanted formatting changes
    • Allow option to specify either fish_indent --only-indent or fish_indent for formatting a file.
  • Update docs for using initializationParams in the client configuration
  • remove fish-lsp logger
    • remove fish-lsp logger from the src/cli.ts file
    • remove fish-lsp logger from the completions
    • remove fish-lsp logger utilities from the src/logger.ts file
  • Refactor unused files & data-structures
  • Read a user's specific configuration they have set
    • env_variables could be set via zod
    • set options via cli flags, fish-lsp start --enable ... --disable ...
    • use builtin fish variables for generating defaults: $__fish_config_dir, $fish_function_path, $__fish_user_data_dir
  • Supporting fish feature flags and handling proper syntax changes

Server Features and Providers

  • Add src/parsing/emit.ts file for emitting a FishSymbol to call a Function. This would disable diagnostics causing false positives for users who like to use a lot of event handlers in their fish config
  • Add Diagnostics
    • add a diagnostic queue to store diagnostics

    • enable/disable specific features (more info available here):

      • Error - missing end to block
      • Error - missing switch/case fall through check case '*' or case \*
      • Warning - prefer command/builtin prefix for commands or builtins
      • Warning - missing completions file from a functions/<file>.fish
      • Test different message formats
      • disable/enable via env variables
      • ...add more features...
    • write verbose tests for each new diagnostic

  • Add CodeActions
    • Create completions file
    • Quickfix diagnostic error
    • Rename autoloaded filename (for a fish function), that doesn't have a matching function name
    • Prefer command prefix for possible aliased shell commands.
    • Move function in ~/.config/fish/config.fish to it's own file, ~/.config/fish/functions/<file>.fish and call it inline.
    • if statement to and/or equivalent, combiner NEEDS TO BE REMOVED ACCORDING TO FISH V4.0.0 DOCS
  • Add CodeLens support (CURRENTLY WE USE INLAY HINTS INSTEAD OF CodeLens)
    • Decide what would be useful to display
      • Local reference count
      • return $status values for functions
      • type -t
  • Add CommandExecutor provider
  • Add function SignatureHelp provider.
    • semi complete, needs more support. (Specifically struggles with determining what the current token type is)
    • add support to enable via CompletionItem
    • add function _ -a first second third -d 'a function description' support for parsing the values out of the options, to then be used as a more traditional signature handler
  • Add set_color Color Presentation to the server, for displaying how the shell would render output.
    • Could be toggled via a server command
    • color theme variables as well
  • FormatOnType provider (useful for small files)
    • add to config
  • Enable server via shebang's:
    • #!/usr/bin/fish
    • #!/usr/local/bin/fish
    • #!/usr/bin/env fish
  • Add DocumentHighlight provider
  • Extend symbol definitions recognized by the server (DONE BY ./src/parsing/):
    • variables created by fish_opt
    • argparse commands
    • alias names
    • set names
    • read names
    • alias names
    • source names
    • for loop variable names
    • function names (both variables and functions)
    • abbr names (would theoretically need to be able to parse a abbr --set-cursor --function)
    • include theme variables
    • event handlers for function _ --on-event event
    • universal variables
  • Descriptions for array indexing: echo $PATH[-1..2]
    • ensure array indexes are: 1 >= idx <= -1
  • status variable documentation
    0 is generally the exit status of commands if they successfully performed the requested operation.
    1 is generally the exit status of commands if they failed to perform the requested operation.
    121 is generally the exit status of commands if they were supplied with invalid arguments.
    123 means that the command was not executed because the command name contained invalid characters.
    124 means that the command was not executed because none of the wildcards in the command produced any matches.
    125 means that while an executable with the specified name was located, the operating system could not actually execute the command.
    126 means that while a file with the specified name was located, it was not executable.
    127 means that no function, builtin or command with the given name could be located.
    
  • argparse support
    • if autoloaded function has argparse then use values to create completions
    • check if all args from argparse are included in completion
    • check if all args from argparse have been used _flag_arg
    • use argparse values as definition
  • disable/enable server features through fish-lsp.command options
  • virtual text - fish_prompt in edit_command_buffer.
    • The general idea here is when an edit_command_buffer is opened, we could use the fish_prompt to display the prompt as virtual text inside the buffer.
    • fish_prompt are just ascii characters
    • edit_command_buffer opens an interactive buffer in the /tmp folder, we could either consider all /tmp/*.fish files to have this behavior, or wrap the edit_command_buffer function in another function with variables exported to specify when this should be used.
  • inlay hints - add references or some other feature
    • return $status values for functions
    • exit values?
  • breakpoint support
  • improve conf.d/*.fish support
    • conf.d/*.fish files are really just treated the same as config.fish files, but are sourced before the config.fish file. This means, that something defined in a conf.d/*.fish file will be available everywhere, but might need to called/referenced to use it in an interactive shell.
  • add completion snippets for builtins

Automation and pipelines

  • (POTENTIALLY) Use pnpm instead of yarn
  • Minimize test-suite for master branch's PR compatibility
    • run via: yarn test-hook
  • Include refactoring/tree-shaking help to scripts: yarn refactor
  • Release binary downloadable files, per machine OS
    • need a build pipeline as well
    • handle scope specific dependencies

    NOTE: used bun to complete this, but the binary files are huge so it currently

  • Action for updating fish-lsp.dev documentation on new publishes
    • write script for generating fish-lsp --help screenshot
  • add action testing fish-lsp --help is successfully built on os matrix (would be mac and unix)

Documentation

  • Add new editor configurations:
  • Add fish-lsp.dev website
    • add monaco support -- testing lsp in web-editor
  • Add improved gif file, showcasing lsp's capabilities to README.md
  • include tree-sitter-fish.wasm in downloaded project
  • README.md changes:
    • improve contributing section (add authors icons)
    • license include only MIT
    • add CodeAction gifs for a section in the README (specifically the completion GIF since its already recorded)
    • use a screenshot of the # @fish-lsp-disable feature, instead of the shell code version given
    • add go-to implementation to README.md
  • Extend documentation provided via wiki
    • workflows - guide for creating new workflows
    • testing - guide for writing tests
    • layout - guide for project layout & design patterns via mermaid charts