#FreePalestine. Read our founder's statement

logo

Just code

no cruft: no build systems, no null, no exception handling, no ORMs, no OOP, no inheritence hierarchies, no async/await, no compilation, no dev environments, no dependency hell, no packaging, no git, no github, no devops: no yaml, no config files, no docker, no containers, no kubernetes, no ci/cd pipelines, no terraform, no orchestrating, no infrastructure: no sql, no nosql, no connection poolers, no sharding, no indexes, no servers, no serverless, no networking, no load balancers, no 200 cloud services, no kafka, no memcached, no unix, no OSes

Send me project updates

Darklang puts everything in one box, so you can build CLIs and cloud apps with no bullshit, just code.


️️️Also it's a really enjoyable language to use!

Looking for Darklang-classic?

dark-classic
In development - here’s how things will look shortly

              $ curl https://darklang.com/download | bash 
              
              Darklang installed in ~/.darklang/bin/darklang
              
              Add to PATH via .bashrc [y, n, ?]: y 
              Added to .bashrc. 

              Next you can: # Try the tutorial darklang tutorial # Run some code from the package manager darklang @paul.fizzbuzz 3 # Generate some code darklang prompt "Find ts scripts with more than 600 lines which use the commonjs format"# See available command line optionsdarklang help
              
            
                
                $ darklang @paul.fizzbuzz 3 
                1
                2 
                Fizz
                
              
                
                $ darklang deploy @paul.fizzbuzz /fizzbuzz 
                Deployed to https://furry-squirrel-3562.darklang.io/fizzbuzz in 0.135s
                 
              
                
                $ curl -sSO https://furry-squirrel-3562.darklang.io/fizzbuzz/3 
                1 
                2 
                Fizz
                
              

                $ darklang prompt "Find ts scripts with more than 600 lines which use commonjs format" 

                We need your AI credentials, which will be stored locally in ~/darklang/secrets/

                [1] Login to use Darklang AI service 
                [2] Enter GitHub copilot credentials 
                [3] Enter OpenAI (GPT 3.5/4) credentials 
                [4] Use local model 

                Enter [1-4]: 1 

                Login or register [L, r]? L
                Username: paul
                Password: **************

                Logged in.

                Saved script in ./find-large-ts-cjs.dark in 43.8s

                
dark-file-logo

find-large-ts-cjs.dark

let findLargeTypescriptCommonJSFiles (path : String) =
  Directory.traverse (fun path -> 
    if not (List.oneOf (File.entension path) [".ts", ".mjs", ".cjs"]) then 
      print $"Skipping - wrong file type: {path}" 
    else 
      let contents = File.readString path 
      let lines = String.splitNewlines contents
      if (List.length lines) <= 600 then 
        print $"Skipping - too short: {path}" 
      else 
        let isCommonjs = 
          lines |> List.any (fun line ->
            line |> Regex.matches "/const .* = require(.*)/" 
          ) 
        if isCommonjs then 
          print $"Found one: {path}" 
    )
    
findLargeTypescriptCommonJSFiles "./"
Functional language Simple types using Records and Enums Dynamic languages are great, allowing great flexibility. But now that they've matured and projects have gotten larger, static typing has been layered on top of very dynamic languages, and the intersection is not pleasant. Functional static languages like Darklang have simple Record and Enum types that can model nearly everything with much less complexity. Abstract Data Types made of Record and Enums can model nearly anything, like in Rust, Elm, OCaml and F#
// Record
type Url = {
  scheme : HttpScheme
  domain : String
  port : UInt16
  path : String
  query : Option<String>
}

// Enum (aka Variant, Sum Type, or Abstract Data Types)
type UrlError = 
  | InvalidScheme(String)
  | EmptyDomain
  | InvalidPort(Int64)
  | Unparseable(msg:String, context:String)

// Aliases are just shorthands
type UrlParseResult = Result<Url, UrlError>

We believe Object Oriented programming is a terrible way to model programs, and inheritence is a terrible misfeature. Languages like OCaml, Elm, and F# have shown that nearly all problems can be modeled using ADTs.
Option and Result types instead of null and exceptions I think it's widely accepted that nullis a mistake, and that an Optiontype (aka Optional, Maybe, etc) makes it significantly easier to program. We further believe that Exceptions — which can in most languages be thrown at any point — makes it very frustrating to know that a function actually works. There are no exceptions in Darklang, and we use Result types to manage error cases ? and !operators (similar to Rust, TypeScript, and Clojure) provide ways to ergonomically handle errors without being too annoying (see also Gradual Static Typing) We will admit we have some RuntimeErrors which cannot be caught, but we are working to remove them almost entirely from the language (see Gradual Static Typing for what we're keeping) Garbage Collected It can be fun to satisfy the borrow checker, or manage allocations individually, but it can also be fun to just get working programs immediately. We believe that run-time garbage collection is one of the greatest programming language features, and we're all in Unicode First Languages created last millennium typically use Strings made of bytes, or worse, UTF16 characters, or even worse, Unicode Codepoints! Like Swift, we believe that Characters should represent screen readable characters, like 👨‍👩‍👦‍👦. All characters in Darklang represent Extended Grapheme Clusters: one character that you see on screen. Naturally, working on Unicode Codepoints and normal bytes is also well supported.
Runs Instantly Instantly run any package from the CLI: darklang @username.functionName arg1 arg2 Darklang has a new model of sharing programs. Any function in the package manager can be called directly from the command line (so long as we can figure out how to coerce the command line arguments correctly)
$ darklang @paul.fizzbuzz 10
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz 
We designed this to allow you to share scripts with your team, or the whole world. We support private packages , with individual, team, or role-based access controls. You can even have functions that run server-side without allowing the user to see credentials, for example for providing customer support tools to your team. Functions can also be run from the web, Slack, Discord, etc We're building safety features, to ensure that functions can't just steal all your IDs and wallets and whatever. Darklang asks for permissions when you call a function, and a static analysis is run to collect all permissions needed.
$ darklang @hacker.stealThings "Hi there"
> @hacker.stealThings requires the following permissions
>   Makes Http requests to unknown domains
>   Reads any file
>   Executes any file
> Continue? [N, y] y
> These are unusual permissions. Are you sure [N, y] y
Ha ha, you're own3d

$ darklang @mycompany.internal.createMonthlyReport
> @mycompany.internal.createMonthlyReport requires the following
> permissions
>   Makes Http GET requests to stripe.com/api/ETC
>   Makes Http POST requests to drive.google.com
> Continue? [N, y] y
Report initiated and stored at https://drive.google.com/u/asj599b3/5288942sdfsdf3.pdf
Instantly run programs as you write them Darklang is designed for a really fast iterative loop Single binary to install means no environments or containers to set up. Install it now! Coming early 2024 Packages are streamed from the package manager automatically – no npm install step darklang is interpreted — no compilation step required, programs run immediately
    We plan to add background compilation in the future, combined with pre-compiled packages in the package manager
Gradual Static Typing allows running programs with incorrect types so you don't need to fix all the types in your program while getting one path working Generate darklang code automatically using LLMs and GitHub Copilot
Next-gen package management Darklang has a rather unique package manager, where functions and types are individually versioned and immutable, taking a lot of the hassle out of package management. Only download the specific package items you use Only upgrade the specific package items you use Automated dependency upgrades, as we track deprecation status, and know what functions are pure and safe to update. Different packages can rely on different versions of other packages Use multiple versions of the same package item at once: allows testing new versions without having to change an entire package version, lowering risk. Share pre-release functions trivially, without contributors needing to check out your git repo or set up anything The package manager functions as a source repository no need for uploads, releases or other synchronization. No git or GitHub required (but you can sync to GitHub if you prefer). Gradual Static Typing Gradual Static Typing allows running incomplete programs so you don't need to ensure everything type checks when you're getting one path working While prototyping, just run code until you hit a type error After prototyping, run the full type checker to gain confidence your whole program works Full type-checking hints in VSCode or in LSP editors ! and ? operators allow easy error handling while you prototype Automatic refactoring converts ! into proper error handling Async runtime Fully asynchronous runtime Darklang has a fully asynchronous runtime, so making a Http call or reading a file doesn't block the runtime. No async / await Adding async and await keywords to every language was a mistake. It exposes the complexity of concurrency and multi-threading to languages which were originally designed for simplicity. Concurrent and parallel execution via data-dependencies

When you make an async request, it first waits for any arguments that are async, and starts when they're done. If another function call needs to use the result, it will wait for it before starting.

Since darklang values are immutable, there won't be any race conditions from this.

Powerful escape hatches We provide powerful escape hatches if you need async ordering that doesn't match the data dependencies of your program.
Instant cloud deployment Optional Instant cloud deployment of code (to our cloud or yours), with instant creation of DBs, API endpoints, and worker queues, with no containers, no cold starts, no orchestration, or other devops/cloud engineering required Designed for GenAI Works with GitHub Copilot We redesigned the dark language and tooling to enable GenAI-generated programs, including exposing language tools to GenAI tools, allowing running partial and incomplete programs safely, and ensuring access to significant context to GenAI tools Build short CLI programs from prompts darklang prompt "find all js files which don't have a CSS file of the same name" Use any LLM: darklang's fine-tuned models , local OSS models, commerical models via API, or using GitHub Copilot Build vendor SDKs from prompts and OpenAPI docs Build complex programs with darklang AI agents Works with your Editor VSCode Extension LSP support for other editors Works with GitHub Copilot and other GenAI tools We mention this because Darklang classic required using our editor, and that's no longer the case. Open source We expect to fully open source Darklang, which is currently source available, early 2024