# Your first Ruby script

> Write a small Ruby script in a text editor, check it with wol script check, run it with wol script run, and see what WolOS asks before a script changes anything.

Source: https://wolos.org/manual/ruby-script

## What it is

A script is a text file with commands in it. You write it once, and from then on one command runs all of them, in order, every time the same way. WolOS runs scripts written for the shell and scripts written in Ruby, a programming language that reads almost like English. Ruby is part of every WolOS, so there is nothing to install.

Two commands do everything on this page:

- `wol script check` reads a script and tells you about mistakes without running any of it;
- `wol script run` runs it.

## Why WolOS does it this way

A script runs with your permissions, and scripts are often copied from somewhere. So WolOS runs every script the same careful way. It never runs one as root. It hands your arguments to the script exactly as you typed them. It leaves the passwords and keys your terminal may hold out of the script's reach. And when a script asks WolOS to change something (a setting, an app, Do Not Disturb), you see a sheet on screen first and decide, just as for any helper. Every run is written down in System Settings > Assistants & Automation, so you can see later what ran and when.

## How

### 1. Write the script

Open **Text Editor** (Search: "text"), and type:

```ruby
#!/usr/bin/env ruby
# Greets you and says how many files are in a folder.
# How: wol script run hello.rb Documents
# frozen_string_literal: true

folder = ARGV.fetch(0, 'Documents')
path = File.join(Dir.home, folder)
count = Dir.children(path).length
puts "Hello, #{ENV.fetch('USER')}!"
puts "#{folder} holds #{count} files and folders."
```

Save it in your home folder as `hello.rb`.

What each line does:

| Line | Means |
|---|---|
| `#!/usr/bin/env ruby` | The first line says which language the file is in. WolOS also knows a Ruby script by the `.rb` at the end of its name. |
| `# …` | A comment, for people. The first comments say what the script does and how to start it. |
| `# frozen_string_literal: true` | A habit of careful Ruby: the texts in the script cannot be changed by accident. |
| `folder = ARGV.fetch(0, 'Documents')` | The first argument you give the script, or Documents when you give none. |
| `path = File.join(Dir.home, folder)` | Builds the path of that folder inside your home folder. |
| `count = Dir.children(path).length` | Counts what is in it. |
| `puts "…"` | Prints a line. `#{…}` inside the quotes puts a value into the text. |

### 2. Check it

Open a terminal (Super+Return) and type:

```
wol script check hello.rb
```

When everything is right you see one line:

```
hello.rb: ruby script, parses and rubocop is clean
```

*Parses* means Ruby understood every line. *Rubocop is clean* means the style checker found nothing to improve; it comes with the Developer module, and without it the check reads the script only. Nothing in the script ran.

If something is wrong, you see one sentence per problem, with the line and the column of the file above it. Fix the line in Text Editor, save, and check again.

### 3. Run it

```
wol script run hello.rb Pictures
```

You see:

```
Hello, aliceliddell!
Pictures holds 12 files and folders.
```

`Pictures` was handed to the script as its first argument. Without it, the script counts Documents.

### 4. Let it change something, with your say-so

Scripts become useful when they act. Add these lines at the end of `hello.rb`:

```ruby
system('wol', 'focus', 'on', exception: true)
puts 'Do Not Disturb is on.'
```

Run it again. Because the script now asks WolOS to turn on Do Not Disturb, a sheet appears and names the script (`script:hello.rb`) and what it wants to do. Click **Allow Once**, and the script continues. **Deny** stops that change, and the script stops with an error. **Always Allow** lets this script do this kind of change from now on without asking; you can take that back in System Settings > Assistants & Automation.

> **Tip:** Write the words of a command separately, as `system('wol', 'focus', 'on')` does, never as one text. Then a folder name with a space or a quote mark in it can never be mistaken for another command.

### 5. See what ran

System Settings > **Assistants & Automation** lists every script run: which script, when, and how it ended. The arguments are not listed, because they may hold private words.

## What a script may and may not do

| A script | |
|---|---|
| Runs as you | Yes. `sudo wol script run` is refused. |
| Reads and writes your files | Yes, like any program you start. Be as careful with a script from somewhere else as with any program. |
| Changes settings or apps through `wol` | Only after you allow it on the sheet. Changes that affect everyone also ask for an administrator's password. |
| Reads the system through `wol` (battery, disks, settings) | Yes, without asking. |
| Sees passwords and keys stored in your terminal | No. It gets your name, your home folder, your language and the desktop, and nothing else from your terminal. |

## A worked example

Alice wants a quiet hour while she backs up her photos. She writes `backup.rb`:

```ruby
#!/usr/bin/env ruby
# Turns Do Not Disturb on while it makes a copy of a folder.
# How: wol script run backup.rb Pictures
# frozen_string_literal: true

folder = ARGV.fetch(0)
system('wol', 'focus', 'on', exception: true)
system('tar', 'czf', "#{folder}.tar.gz", '-C', Dir.home, folder, exception: true)
puts "Saved #{folder}.tar.gz"
```

`wol script check backup.rb` says it parses. `wol script run backup.rb Pictures` shows the sheet for Do Not Disturb; she clicks **Always Allow**, and the copy `Pictures.tar.gz` appears in the folder she ran it from. Next Sunday she runs the same line again, and this time no sheet appears.

## If something goes wrong

| What you see | What to do |
|---|---|
| `wol: hello.rb: no such script (or it is not text)` | The file is not where you are, or the name is different. Check with `ls`, or give its path: `wol script run ~/hello.rb`. |
| `wol: tidy.py is a python3 script; wol script runs sh, bash and ruby.` | Only shell and Ruby scripts run through `wol script`. |
| A message about line 7, column 12 | Ruby or the style checker found a mistake there. Open the file, go to that line, fix it, save, check again. |
| `` `fetch': index 0 outside of array bounds `` | The script needs an argument and got none. Add it after the file name. |
| `No such file or directory @ dir_initialize` | The folder you gave does not exist in your home folder. Check the spelling (capitals matter). |
| The script stops after you clicked **Deny** | That is the point of the sheet. Run it again and allow, or change the script. |
| A program the script uses is not found | Scripts get a fixed list of places to look for programs. Use programs that come with WolOS, or give the full path. |

The [Scripts and shells](/manual/scripts-and-shells) page goes further: shell scripts, running a script on another computer, and choosing the shell of your terminal.
