Shell scripts,
in plain English.

aish reads a script line by line. Each line is a natural-language instruction. Claude drives bash to make it happen — with variables, loops, conditionals, and everything you'd expect.

install detecting…
curl -fsSL https://www.ai-sh.net/install.sh | sh
or grab a binary: direct downloads →

What a script looks like

deploy.aish
#!/usr/bin/env aish

ask "Which host?" as $host

shell ssh ${host} systemctl is-active nginx
from the previous output, save "up" or "down" as $state

if ${state} == "down":
  restart nginx on ${host} and confirm it's serving
  print "${host}: recovered"
else:
  print "${host}: healthy"
end
what happens
? Which host? web1
  $host = web1

[line 4 shell] $ ssh web1 systemctl is-active nginx
    inactive

from the previous output, save "up" or "down" as $state
  $ echo "down"
  $state = down
Captured state = down (nginx is inactive).

-- if ${state} == "down" → true --

restart nginx on web1 and confirm it's serving
  $ ssh web1 sudo systemctl start nginx && ...
nginx restarted, HTTP 200 from /.

web1: recovered
cleanup.aish
#!/usr/bin/env aish

shell du -sh ~/Downloads/* | sort -hr | head -3
from the previous output, save the biggest file's path as $target and size as $size

ask "Delete ${target} (${size})?" as $ok

if ${ok} == "yes":
  shell rm -rf "${target}"
  print "deleted ${target}"
else:
  print "kept"
end
what happens
[line 3 shell] $ du -sh ~/Downloads/* | sort -hr | head -3
    4.2G  /Users/you/Downloads/old-backup.tar.gz
    1.8G  /Users/you/Downloads/dataset.zip
    420M  /Users/you/Downloads/screencast.mov

from the previous output, save the biggest file's path...
  $target = /Users/you/Downloads/old-backup.tar.gz
  $size = 4.2G
Saved target and size from the top row.

? Delete /Users/you/Downloads/old-backup.tar.gz (4.2G)? yes
  $ok = yes

-- if ${ok} == "yes" → true --

[line 10 shell] $ rm -rf "/Users/you/Downloads/old-backup.tar.gz"

deleted /Users/you/Downloads/old-backup.tar.gz
hosts.aish
#!/usr/bin/env aish
# ./hosts.aish --var hosts=web1,web2,web3

for $h in ${hosts}:
  ssh ${h} and get /var disk use percentage as number, save as $pct
  if ${pct} > 85:
    print "${h}: WARNING ${pct}%"
  else:
    print "${h}: ok (${pct}%)"
  end
end
what happens
-- for $h = web1 --
  $ ssh web1 "df /var | awk 'NR==2 {gsub(/%/,\"\"); print $5}'"
    68
  $pct = 68

-- if ${pct} > 85 → false --
web1: ok (68%)

-- for $h = web2 --
  $ ssh web2 "..."
    92
  $pct = 92

-- if ${pct} > 85 → true --
web2: WARNING 92%

-- for $h = web3 --
  $ ssh web3 "..."
    41
  $pct = 41

-- if ${pct} > 85 → false --
web3: ok (41%)
mount.aish
#!/usr/bin/env aish

run lsblk and find the drive that is 10.9T, save as $drive
mount ${drive} at /mnt/media and verify it's writable
print "mounted ${drive} at /mnt/media"
what happens
run lsblk and find the drive that is 10.9T, save as $drive
  $ lsblk -o NAME,SIZE,TYPE | grep disk
    sda   2T      disk
    sdb   10.9T   disk  ← match
  $drive = /dev/sdb
Saved $drive = /dev/sdb (the 10.9T disk).

mount ${drive} at /mnt/media and verify it's writable
  $ mkdir -p /mnt/media && mount /dev/sdb /mnt/media
  $ touch /mnt/media/.wtest && rm /mnt/media/.wtest
Mounted and writable.

mounted /dev/sdb at /mnt/media
aish (interactive)
$ aish
aish repl — Ctrl-D or 'exit' to quit

aish> how many processes am I running?
  $ ps -A | wc -l
You're running 412 processes.

aish> which three are using the most memory?
  $ ps -A -o pid,comm,%mem --sort=-%mem | head -4
Top three by memory: WindowServer (6.4%), Google Chrome Helper (4.1%), Code Helper (3.0%).

aish> kill the google chrome helper that's using the most memory
  $ ps -A -o pid,comm,%mem --sort=-%mem | grep "Chrome Helper" | head -1
    47218  Google Chrome Helper  4.1
  $ kill 47218
Killed PID 47218.

aish> exit
why it works

Natural-language shell. Type what you want; Claude figures out the command, runs it, and reads the output.

Context persists. Line 2 knew which process to kill because line 1 had already pulled the top-memory list.

Variables carry over. Anything you capture via set_var or ask is still there on your next line.

Multi-line blocks buffer. Open a for or if; the prompt indents until end closes it.

What's in the box

$

Bash tool

Claude picks the right shell command to run for each instruction, reads the output, and chains follow-ups.

{}

Variables

Preset with --var, capture with set_var, or write ask "prompt" as $x. Runtime vars are also exported into bash.

↻

Control flow

for, if/else, and end — decided by the runtime, not the LLM. Deterministic branching over discovered lists.

▮

Shell + print

shell "<cmd>" runs a fixed command and injects the output into context. print writes straight to your terminal — zero LLM cost.

⌘

Interactive REPL

Run aish with no args for a natural-language shell. Same tools, same variables, same context.

#!

Shebang scripts

#!/usr/bin/env aish + chmod +x. Your .aish files run like any other executable.

Direct downloads

Or use the install script above. Binaries are static Go builds — no runtime dependencies.

Try it in ten seconds

curl -fsSL https://www.ai-sh.net/install.sh | sh

Requires an Anthropic API key. Store it in an aish.json file next to the binary — e.g. /usr/local/bin/aish.json on macOS/Linux, or C:\Program Files\aish\aish.json on Windows. The ANTHROPIC_API_KEY env var works too.