evoke

Examples · 01 of 06

Run everyday Mac tasks from the terminal, in plain words.

Type "set the volume to 40 percent" in your terminal, and evoke sets it. A reflex is a small program you install and ask for in your words. Fifteen reflexes for everyday Mac tasks install with one line. This example runs today on a Mac, and every file is on GitHub.

The request and the result

01

Three sentences, three outcomes.

A volume change runs at once. A less certain request asks first, and can keep your phrase as an example. A restart asks every time.

~
$ evoke "restart the computer" power action="restart" · destructive · weakest: route 0.98 Make the laptop restart now? [y]es [n]o [t]each > n [2]
  1. 1Sure enough, so it ran. «40 percent» is a number read from your sentence and checked against the range 0 to 100. The least sure answer was 0.96, and a change runs without a question at 0.9 or above.
  2. 2«kill» meant off, but only at 0.86. Under 0.9, so evoke asked first. Typing t, for teach, saved your phrase as an example in a file of yours, then ran.
  3. 3Sure at 0.98, and it still asked. Its author marked power destructive, so it asks every time. No number and no flag skips that question. [2] means you answered no.

Every line is from a session in evoke's tests, which run on every change. The classifier's numbers in it come from a file written for the test, so yours will differ. How sure evoke must be to run →

The collection

02

What each of the fifteen reflexes does.

Together they are evoke's collection, and one command installs them all. Each prints one short line about what it did.

ReflexWhat it doesEffect
awakeKeeps the laptop awake for a while, or until you stop it.write
downloadSaves a file from a URL to your Downloads folder, or to one of your folders.write
lockLocks the screen.write
mailStarts an email in your mail app. Nothing is sent until you press send.write
noteAdds a dated line to your notes file.write
openOpens one of your folders.read
powerRestarts the laptop or shuts it down.destructive
screenshotCaptures the screen, a window or a selection.write
sleepPuts the laptop to sleep.write
soundMutes or unmutes, or turns the volume up or down.write
timerCounts down, then rings.write
trashEmpties the trash.destructive
visitOpens one of your sites, in a private window if you ask for one.read
volumeSets the output volume.write
wifiTurns Wi-Fi on or off.write
  1. 1The effect sets the bar. A reflex that only reads runs without a question at 0.8 or above, one that writes at 0.9, and a destructive one always asks.
  2. 2Three start inactive. open needs your folders, visit your sites and note your notes file. Step 5 below gives them what they need.
  3. 3Twelve run a JavaScript file, so they need Node 24 or newer. open and trash run a program the Mac already has.

The collection, in the manual →

Inside one reflex

03

A reflex is a manifest, and usually a short program.

This is volume. The manifest says what it does and what to ask you. The program runs one AppleScript command. Ten others are built the same way. open and trash are a manifest alone, which names a program the Mac already has.

volume/reflex.tomlthe collection's
reflex = 1

description = """
Set the output volume to a percentage.
From 0, silent, to 100, for everything the laptop plays."""

not_for = [
  "muting or unmuting",
  "turning it up or down by an amount",
  "one app's volume",
  "changing the screen brightness",
  "asking what the volume is",
]
tags = ["sound"]
effect = "write"
confirm = "Set the volume to {level}?"
run = "volume.mts"
platforms = ["macos"]

[needs]
runs = ["osascript"]

[args.level]
ask   = "How loud, in percent?"
pick  = "number"
range = [0, 100]

[examples]
"set the volume to 35 percent"  = { level = "35 percent" }
"volume 60%"                    = { level = "60%" }
"bring the sound up to seventy" = { level = "seventy" }
"drop the volume to 20 percent" = { level = "20 percent" }
"set the volume to 40"          = { level = "40" }
"turn the sound down to 10"     = { level = "10" }
"mute the sound"                = false

[tests]
"put the volume at 100 percent"         = { level = "100 percent" }
"make the speakers twenty five percent" = { level = "twenty five percent" }
"lower the volume a little"             = false
"set the volume for me"                 = { level = false }
"unmute my speakers"                    = false
"turn the brightness up to 70"          = false
"how loud is it right now"              = false
  1. 1The manifest is how you ask for it. A description, what it is not for, one input read as a number from 0 to 100, and example sentences.
  2. 2The program checks the platform first. On another system it stops at once and says it runs on macOS only. On a Mac it runs osascript and returns one line.
  3. 3Every file is on GitHub. The collection is MIT-licensed, so you can copy a script into a reflex of your own.

Wrap a script of your own →

One boundary

04

A value outside its range never reaches the program.

The manifest gives the volume a range of 0 to 100. Your sentence chooses the value. evoke checks it against the range before the program sees it.

evoke
$ evoke "set the volume to 150 percent"
  How loud, in percent?  150 percent is outside 0–100  > 40
  volume level="40"  0.96

evoke asked the input's own question, with the reason on the same line. Your answer was checked the same way, then volume ran with 40. evoke guarantees that every value is one the reflex allows. It cannot guarantee that it read you right, which is why a bar decides what runs without a question. When evoke asks for a value, in the manual → What can run, and what cannot →

Set it up

05

Set it up on your Mac, from nothing to your first sentence.

Seven steps in your terminal. Every output line below comes from a session in evoke's tests. If a step stops, the line it prints ends with the command that fixes it. Each stop and its fix, on Get started →

  1. Install evoke

    The script downloads the release built for your Mac, checks it against the release's checksums, and puts evoke in ~/.local/bin. If it prints a line that begins «add it to your PATH», run the command on that line first.

    curl -fsSL https://evoke.build/install.sh | sh
  2. Give evoke a key

    The classifier that reads each sentence is Jev, TypeSafe AI's model. Without a key, your first sentence stops and names the one it needs. [3] means evoke needs something from you.

    evoke
    $ evoke "lock the screen"
      jev needs TYPESAFE_API_KEY, a key from typesafe.ai  →  export TYPESAFE_API_KEY=<value>
    [3]

    Get a key from TypeSafe AI, then export it. evoke reads it from your shell when it decides, and never writes it to a file. Each decision is one request, billed to your key, and a sentence you repeat is answered from a local cache.

    export TYPESAFE_API_KEY=<value>
  3. Have Node 24 or newer

    Twelve reflexes run a JavaScript file, so evoke add looks for node on your PATH and records where it is. Install Node 24 or newer from nodejs.org first. If you install it later, evoke sync records it.

  4. Install the collection

    Each row names a reflex, where it came from and at which version, its effect, and what it runs. Your rows show the collection's newest version. No code runs while it installs.

    evoke
    $ evoke add evoke-build/reflexes
    + awake       evoke-build/reflexes/awake 0.1.0       write        runs awake.mts
    + download    evoke-build/reflexes/download 0.1.0    write        runs download.mts
    + lock        evoke-build/reflexes/lock 0.1.0        write        runs lock.mts
    + mail        evoke-build/reflexes/mail 0.1.0        write        runs mail.mts
    + note        evoke-build/reflexes/note 0.1.0        write        runs note.mts
    + open        evoke-build/reflexes/open 0.1.0        read         runs open
    + power       evoke-build/reflexes/power 0.1.0       destructive  runs power.mts
    + screenshot  evoke-build/reflexes/screenshot 0.1.0  write        runs screenshot.mts
    + sleep       evoke-build/reflexes/sleep 0.1.0       write        runs sleep.mts
    + sound       evoke-build/reflexes/sound 0.1.0       write        runs sound.mts
    + timer       evoke-build/reflexes/timer 0.1.0       write        runs timer.mts
    + trash       evoke-build/reflexes/trash 0.1.0       destructive  runs osascript
    + visit       evoke-build/reflexes/visit 0.1.0       read         runs visit.mts
    + volume      evoke-build/reflexes/volume 0.1.0      write        runs volume.mts
    + wifi        evoke-build/reflexes/wifi 0.1.0        write        runs wifi.mts
      inactive  note: config "file" is not set      →  evoke config note file <value>
      inactive  open: vocabulary "places" is empty  →  evoke vocab places add <word> "<meaning>"
      inactive  visit: vocabulary "sites" is empty  →  evoke vocab sites add <word> "<meaning>"

    A reflex runs as you, held by the kernel to what its manifest declares, the line under each row. Read what you install: every file is on GitHub.

  5. Give three reflexes your words

    The inactive lines above each end with the command that fixes them. In the first line, desktop is your word and «The desktop.» its meaning, which the classifier reads. The path goes only to the reflex. The notes file is a path under your home.

    evoke
    $ evoke vocab places add desktop "The desktop." --value "~/Desktop"
    + vocab/places.toml  desktop = { what = "The desktop.", value = "~/Desktop" }
    $ evoke config note file "~/notes.txt"
    + evoke.toml  [config.note] file = "~/notes.txt"

    For visit, add a site the same way:

    evoke vocab sites add github "GitHub." --value https://github.com
  6. Look at a decision before it runs

    evoke try decides and runs nothing. It shows which reflex, each value with what it stands on, and what would happen: here, 0.86 is under 0.9, so it would ask first.

    evoke try
    $ evoke try "kill the wifi"
      "kill the wifi"
    
      which reflex            wifi 0.95   (none of them 0.03 · power 0.01)
                              Turn Wi-Fi on or off.
      state                   off 0.86   (on 0.10 · not said 0.04)
                              asked a second way: off 0.86; the less sure of the two counts
                              is it off? yes 0.95
      → waits for a yes: wifi state="off" · write · weakest: state 0.86
        a write runs at 0.90 or more
  7. Type your first sentence

    The indented line is evoke's own: the call it chose, and how sure it was. The last line is the reflex's result.

    evoke
    $ evoke "set the volume to 40 percent"
      volume level="40 percent"  0.96
    volume 40%

Next, teach evoke a phrase of yours, or wrap a script of your own. The manual's first ten minutes carry on from here.