Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Ecko LanguageNew to Visual Studio Code? Get it now.
Ecko Language

Ecko Language

ecko

|
1 install
| (0) | Free
Language support for Ecko: completion, hover, go-to-definition, and diagnostics via the ecko language server, plus syntax highlighting and snippets.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Ecko for VS Code

Language support for Ecko, a small language for work that is not.

Diagnostics, completion, hover, go-to-definition and formatting come from ecko lsp, which is the compiler itself, so your editor cannot disagree with a build. Syntax highlighting and 37 snippets work with no server at all.

What Ecko looks like

Ecko is for work where a failure costs money: transaction streams, catalog syncs, backfills that run for days, APIs that have to stay up. It is built around what happens when something goes wrong.

A failure is a value you catch, with a kind that says what happened. This job sets a malformed row aside, keeps going, and stops on anything it did not plan for:

import std.json

rows = [r"""{"id": 1, "cents": 1250}""", r"""{"id": 2, "cents": """, r"""{"id": 3, "cents": 990}"""]

mut total = 0
mut rejected = []
for line in rows {
    try {
        row = json.decode(line)
        total = total + row.cents
    } catch (e) {
        # A malformed row is set aside. Anything else stops the job, loudly.
        match get(e, "kind") {
            "parse" => {
                rejected = push(rejected, line)
            }
            _ => error(e)
        }
    }
}
print("{total} cents, {len(rejected)} rejected")
2240 cents, 1 rejected

A mistake fails on the line that made it. Reading past the end of a list or overflowing an integer is an error right there, not a null or a wrapped number that turns into a wrong total three steps later:

xs = [1, 2, 3]
try { print(xs[9]) } catch (e) { print("caught: {e.message}") }

mut total = 9223372036854775807
try { total = total + 1 } catch (e) { print("caught: {e.message}") }

Contracts catch what types cannot:

# Boolean contracts catch what types cannot.
@requires(amount > 0)
@ensures(result >= 0)
fn fee(amount) = amount * 3 // 100

print(fee(1250))
print(fee(900))

You see most of this before anything runs. ecko check runs ahead of every program and refuses undefined names, wrong arity and use before definition. That same analysis is what this extension shows you as you type.

There is more: pattern matching over union types, pipelines, sql { ... } blocks with real bind holes, share-nothing concurrency, and a standard library that is already installed. import std.http is an HTTP server. import std.sql is SQLite. ai[T] calls a model and checks the answer against your own types; with no API key it runs in a deterministic offline mock mode, so code that uses a model tests like any other code.

Try it

Paste any example into a file and run it:

ecko example.ecko

Or try the language in your browser first. The playground is the real compiler built to WebAssembly, running client-side with no backend.

What this extension gives you

From the language server (needs the ecko binary):

  • Live diagnostics as you type - parse errors, undefined names with did-you-mean, arity mismatches, use before definition, non-exhaustive matches, unreachable code, unused imports and variables, shadowed builtins, and unwrapped credentials
  • Completion for keywords, builtins, std modules, your own top-level functions, types and variables, and a module's members after a .
  • Hover showing signatures for your functions and labels for builtins
  • Go to definition, document symbols for the outline and breadcrumbs, and workspace symbol search
  • Find All References and occurrence highlighting, scoped to the open file and scope-aware - a name shadowed in an inner block resolves to its own declaration, not to every occurrence of the spelling
  • Quick fixes on five diagnostics: correct a misspelled name to the suggestion the compiler already computed, remove an unused import, prefix an unused binding with _, declare a reassigned binding mut, or fill in the missing arms of a non-exhaustive match
  • Semantic highlighting, coloured by the compiler rather than the grammar, so std modules and types are told apart from ordinary names
  • Format Document, the same result as ecko fmt

Always, with no server:

  • Syntax highlighting for .ecko, covering string interpolation, raw and byte strings, decimal literals, sql { ... } blocks, contract and tool annotations, the ai clauses (using, with, on, -> stream), and ## documentation comments
  • 37 snippets - match, try, @requires, @ensures, sql, template, secret, ai[T] and the rest
  • Auto-closing brackets and quotes, indentation rules, and folding via # region / # endregion

Requirements

The editing intelligence is served by ecko lsp, so you need the binary. It is a single file with nothing to configure:

curl -fsSL https://ecko.sh/install | sh

The extension looks for it in this order:

  1. ecko.server.path in your settings
  2. the ECKO_BINARY environment variable
  3. ecko on your PATH
  4. ~/.local/bin/ecko, then ~/.ecko/bin/ecko, then /usr/local/bin/ecko

Those fallbacks matter because VS Code and Cursor started from a desktop launcher often do not inherit a shell's PATH, and "the server won't start" is almost always that. Set ecko.server.path to an absolute path if so.

Without the binary you still get highlighting and snippets, and a notice explaining how to switch the rest on.

Learn more

ecko.sh The language
Documentation Guides and reference
Playground Run Ecko in the browser
Packages The official package set
support@ecko.sh Bugs in this extension

Licence

Ecko is proprietary software, free for any use, personal or commercial. It is not open source.

The extension and the language share these terms; the full text is in LICENSE.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft