.
This commit is contained in:
@@ -37,9 +37,51 @@ How simple, lightweight and reliable can an agent be?
|
||||
Ask the agent a question (no quotes needed for simple text):
|
||||
|
||||
```sh
|
||||
./ai.sh what is the capital of Japan?
|
||||
./ai.sh -v what is 2 plus 2
|
||||
./ai.sh -m gpt-4o "write a hello world program in python. save it in ~/"
|
||||
$ ./ai.sh what is the capital of Japan?
|
||||
The capital of Japan is Tokyo.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is 2 plus 2
|
||||
2 plus 2 is 4.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh write a hello world program in python. save it in ~/
|
||||
I've created a Python hello world program at ~/hello.py:
|
||||
|
||||
```python
|
||||
print("Hello, World!")
|
||||
```
|
||||
|
||||
You can run it with `python3 ~/hello.py`.
|
||||
```
|
||||
|
||||
With options:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -v what is 2 plus 2
|
||||
[loaded /home/user/.aish/log.jsonl — 3 messages, $0.0001 spent]
|
||||
[step 1] (reasoning) The user wants to know 2 plus 2.
|
||||
[done] 2 plus 2 is 4.
|
||||
2 plus 2 is 4.
|
||||
[finished — 1 steps, $0.0001 spent]
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -m gpt-4o "write a hello world program in python. save it in ~/"
|
||||
I've created a Python hello world program at ~/hello.py:
|
||||
|
||||
```python
|
||||
print("Hello, World!")
|
||||
```
|
||||
|
||||
You can run it with `python3 ~/hello.py`.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -R what is the capital of France
|
||||
The capital of France is Paris.
|
||||
```
|
||||
|
||||
The agent can run shell commands, read files, and execute multi-step
|
||||
@@ -51,9 +93,23 @@ Describe a command in English. The LLM generates the shell command,
|
||||
prints it, and runs it in your terminal:
|
||||
|
||||
```sh
|
||||
./ai.sh -c show me all files including hidden ones
|
||||
./ai.sh -c find all python files modified this week
|
||||
./ai.sh -c show me disk usage sorted by size
|
||||
$ ./ai.sh -c show me all files including hidden ones
|
||||
$ ls -a
|
||||
. .. .git .gitignore README.md ai.sh
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -c find all python files modified this week
|
||||
$ find . -name '*.py' -mtime -7
|
||||
./scripts/build.py
|
||||
./src/main.py
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -c show me disk usage sorted by size
|
||||
$ du -sh * | sort -rh
|
||||
4.0M ai.sh
|
||||
2.0M README.md
|
||||
```
|
||||
|
||||
### Autonomous mode
|
||||
@@ -61,7 +117,16 @@ prints it, and runs it in your terminal:
|
||||
Give the agent a goal and let it run until done or budget exhausted:
|
||||
|
||||
```sh
|
||||
./ai.sh -a "explore the codebase and summarize the architecture"
|
||||
$ ./ai.sh -a "explore the codebase and summarize the architecture"
|
||||
[autonomous mode — goal: explore the codebase and summarize the architecture]
|
||||
[step 1] $ ls -la
|
||||
[step 2] $ cat ai.sh | head -50
|
||||
[step 3] $ wc -l ai.sh
|
||||
[done] This is a single-file shell script AI agent. It uses curl to call
|
||||
an LLM API and jq to parse JSON. The script has three main parts: config
|
||||
loading, an agent loop that calls the API and executes tool calls, and
|
||||
a logger that writes append-only JSON lines. No build step required.
|
||||
[finished — 3 steps, $0.0003 spent]
|
||||
```
|
||||
|
||||
### Initialize a local agent
|
||||
@@ -70,7 +135,10 @@ By default, aish stores everything globally in `~/.aish/`. To create a
|
||||
self-contained agent for a specific project:
|
||||
|
||||
```sh
|
||||
./ai.sh -i
|
||||
$ ./ai.sh -i
|
||||
Initialized /home/user/myproject/.aish
|
||||
Edit /home/user/myproject/.aish/config.json to change model, budget, etc.
|
||||
Edit /home/user/myproject/.aish/system_prompt.txt to customize the agent's instructions.
|
||||
```
|
||||
|
||||
This creates a `.aish/` directory in the current folder with its own
|
||||
@@ -83,18 +151,52 @@ The agent's answer goes to stdout; status messages go to stderr. So you
|
||||
can pipe the answer into other commands:
|
||||
|
||||
```sh
|
||||
./ai.sh what is the capital of Japan | wc -w
|
||||
./ai.sh list all python files in this dir | grep test
|
||||
./ai.sh what is 2+2 > answer.txt
|
||||
$ ./ai.sh what is the capital of Japan | wc -w
|
||||
5
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh list all python files in this dir | grep test
|
||||
./test_runner.py
|
||||
./test_config.py
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is 2+2 > answer.txt
|
||||
$ cat answer.txt
|
||||
2 + 2 is 4.
|
||||
```
|
||||
|
||||
You can also pipe input in. If no message is given on the command line,
|
||||
stdin becomes the message. If both are given, stdin is appended:
|
||||
|
||||
```sh
|
||||
echo "explain this error" | ./ai.sh
|
||||
cat error.log | ./ai.sh explain this error
|
||||
git diff | ./ai.sh -c generate a commit message
|
||||
$ echo "explain this error" | ./ai.sh
|
||||
The error message indicates a missing semicolon at the end of line 12.
|
||||
Add a `;` after the closing brace to fix it.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ cat error.log | ./ai.sh explain this error
|
||||
Looking at the error log, there are three issues:
|
||||
|
||||
1. Line 5: NullPointerException — the variable `config` was never
|
||||
initialized before use.
|
||||
2. Line 12: FileNotFound — the path `/etc/app.conf` doesn't exist on
|
||||
this system.
|
||||
3. Line 18: Timeout — the API call took longer than 30 seconds.
|
||||
|
||||
The root cause is likely the missing config file. Create it and the
|
||||
other errors should resolve.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ git diff | ./ai.sh -c generate a commit message
|
||||
$ git commit -m "Fix: handle empty config file gracefully
|
||||
|
||||
- Add null check before reading config
|
||||
- Fall back to defaults when config is missing
|
||||
- Log warning when using fallback values"
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
-314
@@ -1,314 +0,0 @@
|
||||
---
|
||||
slug: aish
|
||||
title: AI.sh
|
||||
summary: A simple shell script agent
|
||||
image: https://example.com/cover.png
|
||||
tags: [ai, agent, aiharness]
|
||||
---
|
||||
|
||||
# aish
|
||||
|
||||
```
|
||||
, ,
|
||||
(\____/)
|
||||
(_oo_)
|
||||
(O) -- ai.sh
|
||||
__||__ \)
|
||||
[]/______\[] /
|
||||
/ \______/ \/
|
||||
/ /__\
|
||||
(\ /____\
|
||||
```
|
||||
|
||||
## Idea
|
||||
How simple, lightweight and reliable can an agent be?
|
||||
|
||||
## Solution
|
||||
- One shell script.
|
||||
- Use tried and tested linux programs like curl and jq.
|
||||
- Log file is simple so you can read it, and it is used for agent context.
|
||||
- Just give the agent shell access. No special commands, no context bloat.
|
||||
- Fast
|
||||
- This repo has 2 files.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Ask the agent a question (no quotes needed for simple text):
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is the capital of Japan?
|
||||
The capital of Japan is Tokyo.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is 2 plus 2
|
||||
2 plus 2 is 4.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh write a hello world program in python. save it in ~/
|
||||
I've created a Python hello world program at ~/hello.py:
|
||||
|
||||
```python
|
||||
print("Hello, World!")
|
||||
```
|
||||
|
||||
You can run it with `python3 ~/hello.py`.
|
||||
```
|
||||
|
||||
With options:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -v what is 2 plus 2
|
||||
[loaded /home/user/.aish/log.jsonl — 3 messages, $0.0001 spent]
|
||||
[step 1] (reasoning) The user wants to know 2 plus 2.
|
||||
[done] 2 plus 2 is 4.
|
||||
2 plus 2 is 4.
|
||||
[finished — 1 steps, $0.0001 spent]
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -m gpt-4o "write a hello world program in python. save it in ~/"
|
||||
I've created a Python hello world program at ~/hello.py:
|
||||
|
||||
```python
|
||||
print("Hello, World!")
|
||||
```
|
||||
|
||||
You can run it with `python3 ~/hello.py`.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -R what is the capital of France
|
||||
The capital of France is Paris.
|
||||
```
|
||||
|
||||
The agent can run shell commands, read files, and execute multi-step
|
||||
tasks. Context is saved and resumed on subsequent calls.
|
||||
|
||||
### Command mode
|
||||
|
||||
Describe a command in English. The LLM generates the shell command,
|
||||
prints it, and runs it in your terminal:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -c show me all files including hidden ones
|
||||
$ ls -a
|
||||
. .. .git .gitignore README.md ai.sh
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -c find all python files modified this week
|
||||
$ find . -name '*.py' -mtime -7
|
||||
./scripts/build.py
|
||||
./src/main.py
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -c show me disk usage sorted by size
|
||||
$ du -sh * | sort -rh
|
||||
4.0M ai.sh
|
||||
2.0M README.md
|
||||
```
|
||||
|
||||
### Autonomous mode
|
||||
|
||||
Give the agent a goal and let it run until done or budget exhausted:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -a "explore the codebase and summarize the architecture"
|
||||
[autonomous mode — goal: explore the codebase and summarize the architecture]
|
||||
[step 1] $ ls -la
|
||||
[step 2] $ cat ai.sh | head -50
|
||||
[step 3] $ wc -l ai.sh
|
||||
[done] This is a single-file shell script AI agent. It uses curl to call
|
||||
an LLM API and jq to parse JSON. The script has three main parts: config
|
||||
loading, an agent loop that calls the API and executes tool calls, and
|
||||
a logger that writes append-only JSON lines. No build step required.
|
||||
[finished — 3 steps, $0.0003 spent]
|
||||
```
|
||||
|
||||
### Initialize a local agent
|
||||
|
||||
By default, aish stores everything globally in `~/.aish/`. To create a
|
||||
self-contained agent for a specific project:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh -i
|
||||
Initialized /home/user/myproject/.aish
|
||||
Edit /home/user/myproject/.aish/config.json to change model, budget, etc.
|
||||
Edit /home/user/myproject/.aish/system_prompt.txt to customize the agent's instructions.
|
||||
```
|
||||
|
||||
This creates a `.aish/` directory in the current folder with its own
|
||||
config, system prompt, and log. While `.aish/` exists, all storage is
|
||||
local to that directory. Remove it to return to global mode.
|
||||
|
||||
### Piping
|
||||
|
||||
The agent's answer goes to stdout; status messages go to stderr. So you
|
||||
can pipe the answer into other commands:
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is the capital of Japan | wc -w
|
||||
5
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh list all python files in this dir | grep test
|
||||
./test_runner.py
|
||||
./test_config.py
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ./ai.sh what is 2+2 > answer.txt
|
||||
$ cat answer.txt
|
||||
2 + 2 is 4.
|
||||
```
|
||||
|
||||
You can also pipe input in. If no message is given on the command line,
|
||||
stdin becomes the message. If both are given, stdin is appended:
|
||||
|
||||
```sh
|
||||
$ echo "explain this error" | ./ai.sh
|
||||
The error message indicates a missing semicolon at the end of line 12.
|
||||
Add a `;` after the closing brace to fix it.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ cat error.log | ./ai.sh explain this error
|
||||
Looking at the error log, there are three issues:
|
||||
|
||||
1. Line 5: NullPointerException — the variable `config` was never
|
||||
initialized before use.
|
||||
2. Line 12: FileNotFound — the path `/etc/app.conf` doesn't exist on
|
||||
this system.
|
||||
3. Line 18: Timeout — the API call took longer than 30 seconds.
|
||||
|
||||
The root cause is likely the missing config file. Create it and the
|
||||
other errors should resolve.
|
||||
```
|
||||
|
||||
```sh
|
||||
$ git diff | ./ai.sh -c generate a commit message
|
||||
$ git commit -m "Fix: handle empty config file gracefully
|
||||
|
||||
- Add null check before reading config
|
||||
- Fall back to defaults when config is missing
|
||||
- Log warning when using fallback values"
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```sh
|
||||
# 1. Install dependencies
|
||||
sudo apt install curl jq coreutils # Debian/Ubuntu
|
||||
|
||||
# 2. Add your API key (get one from https://ppq.ai)
|
||||
cat > ~/.aish.conf <<'EOF'
|
||||
DEFAULT_API_KEY="sk-your-key-here"
|
||||
EOF
|
||||
chmod 600 ~/.aish.conf
|
||||
|
||||
# 3. Run it
|
||||
./ai.sh what is the capital of Japan
|
||||
```
|
||||
|
||||
That's it. No build step, no install script, no daemon.
|
||||
|
||||
## Options
|
||||
|
||||
| Short | Long | Description |
|
||||
|-------|------|-------------|
|
||||
| `-c` | `--cmd` | Command mode (generate and run a shell command) |
|
||||
| `-a` | `--autonomous` | Autonomous mode (run until done or budget exhausted) |
|
||||
| `-i` | `--init` | Create local `.aish/` with defaults, exit |
|
||||
| `-x` | `--clear` | Clear the log file and exit |
|
||||
| `-v` | `--verbose` | Show status lines |
|
||||
| `-m` | `--model` | Override model |
|
||||
| `-k` | `--api-key` | API key (or set `PPQ_API_KEY`) |
|
||||
| `-C` | `--max-cost` | Override max cost (USD) |
|
||||
| `-s` | `--max-steps` | Override max steps |
|
||||
| `-t` | `--timeout` | Override overall timeout (seconds) |
|
||||
| `-T` | `--cmd-timeout` | Override per-command timeout (seconds) |
|
||||
| `-r` | `--resume` | Resume from existing log (default: yes) |
|
||||
| `-R` | `--no-resume` | Start fresh (ignore existing log) |
|
||||
| `-h` | `--help` | Show help |
|
||||
|
||||
## Configuration
|
||||
|
||||
### API key
|
||||
|
||||
Create `~/.aish.conf` with your key:
|
||||
|
||||
```sh
|
||||
cat > ~/.aish.conf <<'EOF'
|
||||
DEFAULT_API_KEY="sk-your-key-here"
|
||||
EOF
|
||||
chmod 600 ~/.aish.conf
|
||||
```
|
||||
|
||||
This file lives in your home directory, outside the repo, and is never
|
||||
committed. Any `DEFAULT_*` variable from `ai.sh` can be overridden there.
|
||||
|
||||
### Config priority
|
||||
|
||||
Settings are resolved in this order (first match wins):
|
||||
|
||||
1. CLI flags (`-m`, `-C`, `-s`, etc.)
|
||||
2. Local `.aish/config.json` (if `.aish/` exists in current directory)
|
||||
3. Global `~/.aish/config.json`
|
||||
4. `~/.aish.conf` shell vars
|
||||
5. Built-in defaults in `ai.sh`
|
||||
|
||||
### Storage
|
||||
|
||||
**Global mode** (default): `~/.aish/` holds config, system prompt, and
|
||||
log. The agent has shared global memory — conversations from any
|
||||
directory are logged to the same file and resumed on subsequent calls.
|
||||
|
||||
**Local mode**: Run `./ai.sh -i` to create a `.aish/` in the current
|
||||
directory. While it exists, that directory uses its own config, prompt,
|
||||
and log instead of the global ones.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `curl`
|
||||
- `jq`
|
||||
- coreutils (`date`, `mkdir`, `chmod`, `head`, `cat`, `printf`, `mktemp`, `timeout`, `sync`, `basename`, `sleep`, `wc`, `tail`, `sed`, `grep`)
|
||||
|
||||
```sh
|
||||
# Debian / Ubuntu
|
||||
sudo apt install curl jq coreutils
|
||||
|
||||
# Fedora / RHEL
|
||||
sudo dnf install curl jq coreutils
|
||||
|
||||
# Arch
|
||||
sudo pacman -S curl jq coreutils
|
||||
|
||||
# macOS (Homebrew — coreutils provides GNU versions like `timeout`)
|
||||
brew install curl jq coreutils
|
||||
```
|
||||
|
||||
## Log format
|
||||
|
||||
Each line in `log.jsonl` is JSON with a `source` field:
|
||||
|
||||
| source | event | who |
|
||||
|--------|-------|-----|
|
||||
| `user` | `user_input` | you |
|
||||
| `model` | `response` | the AI |
|
||||
| `aish` | `exec` | script ran a command |
|
||||
| `aish` | `api_error` | script detected an error |
|
||||
|
||||
## Warning
|
||||
|
||||
**This agent has full shell access.** It can run any command on your
|
||||
system — read files, write files, delete data, install software, make
|
||||
network requests. There are no sandboxing or permission restrictions.
|
||||
|
||||
Run it only on a computer, VM, or Qube that is dedicated to agent use.
|
||||
Do not run it on a machine with sensitive data or credentials you cannot
|
||||
afford to lose.
|
||||
Reference in New Issue
Block a user