npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

runflick

v1.0.5

Published

A modern, expressive programming language with a focus on readability and developer experience. Flick features a unique syntax that eliminates parentheses for function calls, making code more natural to read.

Downloads

15

Readme

Flick Programming Language

A modern, expressive programming language with a focus on readability and developer experience. Flick features a unique syntax that eliminates parentheses for function calls, making code more natural to read.

Features

Space-Separated Function Calls - No parentheses needed
🔌 Plugin System - Extensible with built-in plugins (web, files, time, random)
🌐 Web Server (Gazelle) - Built-in HTTP server with routing and nested modules
📦 JavaScript/TypeScript Imports - Use npm packages and Node.js modules seamlessly
🎯 Type Inference - Smart type handling with automatic conversions
🔄 Modern Control Flow - Intuitive syntax for loops and conditionals

Installation

npm install -g runflick

Usage

# Run a Flick file
flick run yourfile.fk

Syntax Examples

Variables

free name = "Alice"          # Mutable variable
lock maxUsers = 100          # Immutable constant
free count = num "42"        # Type conversion

Functions (Tasks)

task greet with literal(name) =>
    print "Hello, " and name
end

greet "World"  # No parentheses!

# Tasks can return values using 'give'
task double with num(x) =>
    give x * 2
end

free result = double 5
print result  # 10

# Tasks can be called without arguments
task sayHello =>
    print "Hello!"
end

sayHello  # Auto-calls even without ()

Ternary Expressions (Inline Assume)

# Inline conditional expressions
free age = 25
free status = assume age >= 18 => "Adult", otherwise => "Minor"
print status  # "Adult"

# Nested ternaries
free score = 85
free grade = assume score >= 90 => "A", otherwise => assume score >= 80 => "B", otherwise => "C"
print grade  # "B"

# Without otherwise (returns null if false)
free result = assume score > 100 => "Perfect"

Conditionals

assume age >= 18 =>
    print "Adult"
maybe age >= 13 =>
    print "Teenager"
otherwise =>
    print "Child"
end

Loops

# For-each loop
each item in items =>
    print item
end

# Range loop
march i from 1 to 10 =>
    print i
end

Groups (Classes)

group Player {
    free num health = 100
    free literal name
    
    task takeDamage with num(amount) =>
        health := health - amount
        print name and " took damage!"
    end
    
    task getHealth =>
        give health  # Return current health
    end
}

free player = Player "Alice"
player/takeDamage 15  # You can also use dot notation! <player.takeDamage 15>

free currentHealth = player/getHealth
print currentHealth  # 85

# Groups without required fields can be instantiated without arguments
group Counter {
    free num count = 0
    
    task increment =>
        count := count + 1
        give count
    end
}

free Counter counter = Counter  # Auto-instantiates
free value = counter/increment
print value  # 1

Blueprints (Interfaces)

blueprint Drawable {
    task draw
}

do Drawable for Player =>
    task draw =>
        print "Drawing player: " and name
    end
end

JavaScript/TypeScript Imports

import {readFileSync, writeFileSync} from "node:fs"
import {resolve} from "node:path"

free content = readFileSync "package.json", "utf-8"
free data = JSON/parse content
print data/name

writeFileSync "output.txt", "Hello from Flick!"

Web Server (Gazelle Plugin)

declare web@3000

route GET "/" =>
    respond "Welcome to Flick!"
end

route POST "/api/users" =>
    free user = body
    respond json={"id": 1, "name": user.name}, status=201
end

# Access request data
route GET "/search" =>
    print query/term
    print headers["user-agent"]
    respond json=query
end

Nested Routing

# main.fk
declare web@8080
use AuthRoutes

route "/" =>
    respond "Home"
end

route "/auth" -> AuthRoutes
# AuthRoutes.fk
declare web@module

route "/login" =>
    respond json={"token": "abc123"}
end

route POST "/logout" =>
    respond json={"success": yes}
end

Built-in Plugins

Files Plugin

declare files

free content = read "file.txt"
write "output.txt", "Hello"
assume exists "config.json" =>
    print "Config found!"
end

Time Plugin

declare time

free timestamp = now
print timestamp

sleep 1000  # Wait 1 second
print "Done waiting"

Random Plugin

declare random

free randNum = random
free dice = randint 1, 6
free shuffled = shuffle myArray
free pick = choice myArray

File Extension

Flick files use the .fk extension.

Keywords

Control Flow: assume, maybe, otherwise, each, march, select, when
Declarations: group, blueprint, task, free, lock, declare, use, import
Statements: print, respond, route, do, for, with, in, from, to, give
Booleans: yes, no
Types: num, literal
Operators: := (assignment), = (assignment/equality), and (concatenation in print), / or . (member access)

Special Features

Return Values

Use give to return values from tasks:

task findFirst with num(threshold) =>
    march i from 1 to 10 =>
        assume i > threshold =>
            give i  # Early return
        end
    end
    give -1  # Not found
end

free result = findFirst 6
print result  # 7

Auto-calling Functions

task greet =>
    print "Hello!"
end

greet  # Auto-calls

# Groups auto-instantiate when assigned with type annotation
group Counter {
    free num count = 0
}

free Counter c = Counter  # Auto-instantiates

Empty Checks

Empty strings, empty arrays, and empty objects are falsy:

assume body =>  # True if body is not empty
    print "Has data"
end

Input Function

The ask function prompts for user input and automatically uses an empty prompt if none is provided:

lock input = ask "Enter your name: "
print "Hello, " and input

# Can be used without prompt
lock value = ask
free result = ask + 1  # Asks with empty prompt, then adds 1

Request Handling (Web Plugin)

Available in route handlers:

  • req - Full request object
  • body - Parsed request body (JSON auto-parsed)
  • query - Query parameters object
  • headers - Request headers object

Example: Complete Web API

declare web@3000
declare files

free database = JSON/parse (read "<path_from_workdir>/db.json")

route GET "/api/users" =>
    respond json=database.users
end

route POST "/api/users" =>
    free user = body
    free userId = database/users/length + 1
    # Add user to database...
    respond json={"id": userId, "name": user.name}, status=201
end

route GET "/api/users/:id" =>
    free userId = query/id
    respond json={"message": "User " + userId}
end

License

ISC