Display HTML and Markdown

Display HTML

Use await div('') to display HTML.

// Name: Display HTML
import "@johnlindquist/kit"
await div(`<h1>Hello World</h1>`)

Open display-html in Script Kit

Display HTML with CSS

Script Kit bundles Tailwind CSS.

// Name: Display HTML with CSS
import "@johnlindquist/kit"
await div(
`<h1 class="p-10 text-4xl text-center">Hello World</h1>`

Open display-html-with-css in Script Kit

Display Markdown

The md() function will convert Markdown to HTML into HTML that you can pass into div. It will also add the default Tailwind styles so you won't have to think about formatting.

// Name: Display Markdown
import "@johnlindquist/kit"
let html = md(`# Hello World`)
await div(html)

Open display-markdown in Script Kit

Discuss "Display HTML and Markdown" on Github

Text Input

Input Text with await arg()

The simplest form of input you can accept from a user is an arg()

// Name: Input Text
import "@johnlindquist/kit"
let name = await arg("Enter your name")
await div(md(`Hello, ${name}`))

Open input-text in Script Kit

Select From a List of Strings

// Name: Select From a List
import "@johnlindquist/kit"
let fruit = await arg("Pick a fruit", [
await div(md(`You selected ${fruit}`))

Open select-from-a-list in Script Kit

Select From a List of Objects

// Name: Select From a List of Objects
import "@johnlindquist/kit"
let { size, weight } = await arg("Select a Fruit", [
name: "Apple",
description: "A shiny red fruit",
// add any properties to "value"
value: {
size: "small",
weight: 1,
name: "Banana",
description: "A long yellow fruit",
value: {
size: "medium",
weight: 2,
await div(
`You selected a fruit with size: ${size} and weight: ${weight}`

Open select-from-a-list-of-objects in Script Kit

Display a Preview When Focusing a Choice

// Name: Display a Preview When Focusing a Choice
import "@johnlindquist/kit"
let heights = [320, 480, 640]
let choices = heights.map(h => {
return {
name: `Kitten height: ${h}`,
preview: () =>
`<img class="w-full" src="http://placekitten.com/640/${h}"`,
value: h,
let height = await arg("Select a Kitten", choices)
await div(md(`You selected ${height}`))

Open display-a-preview-when-focusing-a-choice in Script Kit

Discuss "Text Input" on Github

Select a Path

Select a Path

// Name: Select a Path
import "@johnlindquist/kit"
let filePath = await path()
await div(md(`You selected ${filePath}`))

Open select-a-path in Script Kit

Select a Path with Options

// Name: Select a Path with Options
import "@johnlindquist/kit"
await path({
hint: `Select a path containing JS files`,
onlyDirs: true,
onChoiceFocus: async (input, { focused }) => {
let focusedPath = focused.value
try {
let files = await readdir(focusedPath)
let hasJS = files.find(f => f.endsWith(".js"))
hasJS ? "✅ Found" : "🔴 Didn't find"
} JS files`
} catch (error) {

Open select-a-path-with-options in Script Kit

Drag and Drop

// Name: Drop Example
import "@johnlindquist/kit"
// Note: Dropping one or more files returns an array of file information
// Dropping text or an image from the browser returns a string
let fileInfos = await drop()
let filePaths = fileInfos.map(f => f.path).join(",")
await div(md(filePaths))

Open drop-example in Script Kit

Select from Finder Prompts

// Name: Select from Finder Prompt
import "@johnlindquist/kit"
let filePath = await selectFile()
let folderPath = await selectFolder()
await div(md(`You selected ${filePath} and ${folderPath}`))

Open select-from-finder-prompt in Script Kit

Discuss "Select a Path" on Github

Built-in Editor

Built-in Editor

// Name: Editor Example
import "@johnlindquist/kit"
let result = await editor({
footer: `Hit cmd+s to continue...`,
await div(md(result))

Open editor-example in Script Kit

Load Text in the Editor

// Name: Load Text Into the Editor
import "@johnlindquist/kit"
let { data } = await get(
let result = await editor({
value: data,
// Supports "css", "js", "ts", and "md". "md" is default. More language support coming in future releases.
language: "md",
footer: `Hit cmd+s to continue...`,
await div(md(result))

Open load-text-into-the-editor in Script Kit

Discuss "Built-in Editor" on Github

Built-in Terminal

Use the Built-in Terminal

// Name: Run Commands in the Terminal
import "@johnlindquist/kit"
await term({
//defaults to home dir
cwd: `~/.kenv`,
command: `ls`,
// The footer is optional. All terms continue with the same shortcuts
footer: `ctrl+c or cmd+enter to continue`,

Open run-commands-in-the-terminal in Script Kit

The shell defaults to zsh. You can change your shell by setting the KIT_SHELL environment variable in the ~/kenv/.env, but most of the testing has been done with zsh.

Discuss "Built-in Terminal" on Github

Environment Variables

Read and Write from ~/.kenv/.env

The env helper will read environment variables from ~/.kenv/.env. If the variable doesn't exist, it will prompt you to create it.

// Name: Env Example
import "@johnlindquist/kit"
let KEY = await env("MY_KEY")
await div(md(`You loaded ${KEY} from ~/.kenv/.env`))

Open env-example in Script Kit

Choose an Environment Variable

If you pass a function as the second argument to env, it will only be called if the variable doesn't exist. This allows you to set Enviroment Variables from a list, an API, or any other data source.

// Name: Choose an Environment Variable
import "@johnlindquist/kit"
let MY_API_USER = await env("MY_API_USER", async () => {
return await arg("Select a user for your API", [
await div(
`You selected ${MY_API_USER}. Running this script again will remember your choice`

Open choose-an-environment-variable in Script Kit

Discuss "Environment Variables" on Github


Play with Data in Chrome DevTools

// Name: Play with Data in Chrome DevTools
import "@johnlindquist/kit"
// Will open a standalone Chrome DevTools window
// The object passed in will be displayed
// You can access the object using `x`, e.g., `x.message` will be `Hello world`
message: "Hello world",

Open play-with-data-in-chrome-devtools in Script Kit

Discuss "DevTools" on Github

npm Packages

Install Express from npm

// Name: Express Example
import "@johnlindquist/kit"
let express = await npm("express")
let detect = await npm("detect-port")
let app = express()
app.get("/", (req, res) => {
res.send(`Hello Script Kit!`)
let port = await detect()
await hide() // in case the terminal is open from installing packages
await browse(`http://localhost:${port}`)

Open express-example in Script Kit

You can terminate a long-running process like above from the menubar dropdown menu or by pressing cmd+p from the Script Kit window to list running processes.

Discuss "npm Packages" on Github

Share Scripts

Get Featured

Featured scripts are displayed in:

To get featured, post your script to the Script Kit Github discussions Share page. With a script focused in the Script Kit main window, you can press right or cmd+k to bring up a share menu which will automatically walk you through creating a shareable post for the script.

As a shortcut, hit cmd+s with a script selected to automatically run the "Share as Discussion" process.

Share as a Gist, Link, URL, or Markdown

The Script Kit main window also includes many other share options:

  • Share as Gist cmd+g: Creates as Gist of the selected script, then copies the URL to the clipboard
  • Share as Link opt+s: Creates a private installable kit://link to the selected script, then copies the URL to the clipboard. These links are very long as they encode the entire script into the URL.
  • Share as URL opt+u: Creates a Gist of the selected script, then copies an installable public URL to the clipboard
  • Share as Markdown cmd+m: Copies the selected script as a Markdown snippet to the clipboard
Discuss "Share Scripts" on Github

Add a Keyboard Shortcut

// Shortcut Metadata

Use the // Shortcut metadata to add a global keyboard shortcut to any script

// Shortcut: cmd shift j
import "@johnlindquist/kit"
say(`You pressed command shift j`)
// Shortcut: opt i
import "@johnlindquist/kit"
say(`You pressed option i`)

// Shortcode Metadata

A shortcode allows you quickly run a script without needing to search for it.

To trigger a // Shortcode, type the string of characters from the main menu, then hit spacebar. In this example, you would type oi then spacebar to run this script:

// Shortcode: oi
import "@johnlindquist/kit"
say(`You pressed option i`)

Quick Submit from Hint

A common pattern from Terminal is to quickly submit a script from a hint. Using a bracket around a single character will submit that character when pressed.

import "@johnlindquist/kit"
let value = await arg({
placeholder: "Continue?",
hint: `Another [y]/[n]`,
if (value === "y") {
say(`You pressed y`)
} else {
say(`You pressed n`)

Quick Submit from Choice

If you need to provide a little more information to the user, use a choice instead of a hint. This allows you to provide a full value that will be submitted instead of just the single letter.

import "@johnlindquist/kit"
let value = await arg("Select a food", [
name: "[a]pple",
value: "apple",
name: "[b]anana",
value: "banana",
name: "[c]heese",
value: "cheese",
await div(md(value))
Discuss "Add a Keyboard Shortcut" on Github

Run a Script on a Schedule

Run a Script on a Schedule

Use cron syntax to run scripts on a schedule. The following example will show a notification to stand up and stretch every 15 minutes.

// Name: Stand Up and Stretch
// Schedule: */15 * * * *
import "@johnlindquist/kit"
notify(`Stand up and stretch`)

Open stand-up-and-stretch in Script Kit

Crontab.guru is a great utility to help generate and understand cron syntax.

Discuss "Run a Script on a Schedule" on Github

Watch for File Changes

Watch a Single File

The // Watch metadata enables you to watch for changes to a file on your system.

// Name: Speak File
// Watch: ~/speak.txt
import "@johnlindquist/kit"
let speakPath = home("speak.txt")
try {
let content = await readFile(speakPath, "utf-8")
if (content.length < 60) {
// We don't want `say` to run too long 😅
} catch (error) {

Open speak-file in Script Kit

Watch a Directory

The // Watch metadata uses Chokidar under the hood, so it supports the same glob patterns.

// Name: Download Log
// Watch: ~/Downloads/*
import "@johnlindquist/kit"
// These are optional and automatically set by the watcher
let filePath = await arg()
let event = await arg()
if (event === "add") {
await appendFile(home("download.log"), filePath + "\n")

Open download-log in Script Kit

Discuss "Watch for File Changes" on Github

Read Files

Read Files

// Name: Read Files
import "@johnlindquist/kit"
let pkg = await readFile(
home(".kenv", "package.json"),
await editor({
value: pkg,
language: "json",

Open read-files in Script Kit

Discuss "Read Files" on Github

Create Files

Create a Text File

// Name: Create a Text File
import "@johnlindquist/kit"
let filePath = await path() // Select a path that doesn't exist
let exists = await pathExists(filePath)
if (!exists) {
await writeFile(filePath, "Hello world")
} else {
await div(md(`${filePath} already exists...`))

Open create-a-text-file in Script Kit

Update a Text File

// Name: Update a Text File
import "@johnlindquist/kit"
let filePath = home(`my-notes.md`)
// `ensureReadFile` will create the file with the content
// if it doesn't exist
let content = await ensureReadFile(filePath, "Hello world")
await editor({
value: content,
onInput: _.debounce(async input => {
await writeFile(filePath, input)
}, 200),

Open update-a-text-file in Script Kit

Discuss "Create Files" on Github

Download Files

Download a Single File

// Name: Download a File
import "@johnlindquist/kit"
let url = "https://www.scriptkit.com/assets/logo.png"
let buffer = await download(url)
let fileName = path.basename(url)
let filePath = home(fileName)
await writeFile(filePath, buffer)

Open download-a-file in Script Kit

Discuss "Download Files" on Github

Get, Post, Put, Delete Requests

The get, post, put, and delete methods use the axios API

Make a Get Request

// Name: Get Example
import "@johnlindquist/kit"
let response = await get(
await div(md(response.data.message))

Open get-example in Script Kit

Make a Post Request

// Name: Post Example
import "@johnlindquist/kit"
let response = await post(
name: await arg("Enter your name"),
await div(md(response.data.message))

Open post-example in Script Kit

Discuss "Get, Post, Put, Delete Requests" on Github

Simple Storage

Read and Write Using the db Helper

The db helpers reads/writes to json files in the ~/.kenv/db directory. It's meant as a simple wrapper around common json operations.

// Menu: Database Read/Write Example
// Description: Add/remove items from a list of fruit
let fruitDb = await db(["apple", "banana", "orange"])
// This will keep prompting until you hit Escape
while (true) {
let fruitToAdd = await arg(
placeholder: "Add a fruit",
//allows to submit input not in the list
strict: false,
await fruitDb.write()
let fruitToDelete = await arg(
"Delete a fruit",
fruitDb.items = fruitDb.items.filter(
fruit => fruit !== fruitToDelete
await fruitDb.write()

Open db-store in Script Kit

Discuss "Simple Storage" on Github

Run From the Terminal

In progress...

Discuss "Run From the Terminal" on Github