Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Build a small CLI with ScaiFlux

A 15-minute walkthrough that uses ScaiFlux to scaffold a real, working Python CLI — from empty directory to passing tests — by asking the agent to do the work instead of writing the code yourself. The point isn't the CLI; it's seeing the agentic loop in practice (model → tool call → result → next decision) so you have a mental model for everything else you'll do with ScaiFlux later.

You should have ScaiFlux installed and configured. If not, do install and quickstart first.


What you'll build#

A tiny wordcount utility that takes a path (file or directory) and prints lines / words / characters per file plus a total, with an optional --top N flag to show only the largest files. Roughly 80 lines of Python plus tests.

Why this task? It's small enough to finish in one session, big enough to exercise everything that makes ScaiFlux agentic: file creation, running tests, iterating on a bug, refactoring on request.

Setup#

bash
1
2
3
mkdir ~/projects/wordcount && cd ~/projects/wordcount
scaiflux init       # scaffolds .scaiflux.json + SCAIFLUX.md + .gitignore
scaiflux            # drops into the REPL

Inside the REPL you'll see a banner with the resolved model, the permission mode (workspace-write by default after init), and a hint about /help.


Turn 1 — scaffold the CLI#

Type this and press Enter:

text
1
2
3
4
▸ Write a small CLI tool in cli.py that takes a path argument
  (file or directory) and prints lines/words/chars per file plus
  totals. Use only the Python standard library. Also write tests
  in test_cli.py that I can run with `python -m unittest`.

You'll see ScaiFlux:

  1. Stream a short plan in plain prose.
  2. Invoke write_file(path="cli.py", ...) — you'll see a ● write_file(...) row appear, then when it lands.
  3. Invoke write_file(path="test_cli.py", ...) the same way.
  4. Wrap up with a one-paragraph summary of what got written.

No "here's the code, paste it into a file" — the agent did the filesystem operations itself. That's the point.

Verify:

bash
1
2
3
ls
# cli.py  test_cli.py  .scaiflux.json  SCAIFLUX.md  .gitignore
python cli.py /etc/hostname

Turn 2 — let the agent run the tests#

This is the moment that makes ScaiFlux feel different. Type:

text
1
2
▸ Run the tests and tell me if they pass. If anything's broken,
  fix it and re-run until everything's green.

You'll watch ScaiFlux:

  1. Call bash(command="python -m unittest test_cli.py -v").
  2. Read the output. If a test failed, it'll diagnose, call edit_file(...) on the offending function, re-run, and repeat.
  3. Stop when every test passes.

Tool calls roll past in the terminal in real time:

text
1
2
3
4
5
● bash(python -m unittest test_cli.py -v)  1.1s ✗
  FAIL: test_handles_empty_file …
● edit_file(path=cli.py, old_string=…, new_string=…)  ✓ (42ms)
● bash(python -m unittest test_cli.py -v)  0.9s ✓
  OK

If the model's first attempt was perfect, you might see just one bash call and a "tests pass" reply. Either way, you didn't copy/paste anything — the iteration loop ran inside ScaiFlux.


Turn 3 — add a feature#

Once the baseline is green, ask for the --top N flag:

text
1
2
3
▸ Add a --top N option that, when set, only prints the N largest
  files by word count. Update the tests to cover both the
  unflagged behaviour and the new flag. Run the tests after.

This turn exercises reading existing code before editing it. ScaiFlux will:

  1. Call read_file(path="cli.py") to see what's there.
  2. Call read_file(path="test_cli.py") similarly.
  3. Call edit_file(...) twice — one per file.
  4. Call bash(...) to run the tests.

If the tests don't pass first try, repeat the loop from Turn 2.


Turn 4 — interrupt mid-turn (optional)#

Type:

text
1
2
▸ Refactor cli.py to be more idiomatic — use pathlib, type
  hints, and split the file-walking logic into a helper function.

About a second in, hit Esc. The model stops mid-stream, you'll see — interrupted in the footer, and you're back at a prompt. The partial edits (if any) are visible — ScaiFlux doesn't undo work that already landed; it just halts the turn cleanly.

This is the main "I changed my mind" affordance. The rest of the session continues normally; you can immediately ask for something different.


Turn 5 — review and commit#

text
1
2
▸ Show me the diff vs. an empty workspace. Then write a
  one-line conventional-commit message describing what was built.

ScaiFlux will:

  1. Call bash(command="git init && git add -A && git diff --cached") if there's no git repo yet — or just git diff if there is.
  2. Read the diff and synthesise a commit message.
  3. Print the message but not commit (action verbs without "run" are read-only by default — see slash workflow docs for /commit run if you want the actual commit too).

What just happened (the agentic loop)#

Every turn followed the same shape:

sequenceDiagram autonumber participant U as you participant SF as ScaiFlux participant T as workspace tools U->>SF: prompt loop until done SF->>T: tool call (read / write / edit / bash …) T-->>SF: result Note over SF: decides next step from result end SF-->>U: text summary

The model isn't generating prose for you to act on; it's generating tool calls that the harness executes against your filesystem and shell. ScaiFlux is the glue — it serialises the calls, checks permissions, runs them, feeds results back to the model, and renders the loop in your terminal. The chat surface is the steering wheel; the tool surface is where work actually happens.

Where to go next#

  • CLI reference — every slash command and flag, in one place.
  • REPL walkthrough — narrative tour of the interactive surface (session picker, context indicator, ESC, Poolnoodle mode, /save, …).
  • Serve protocol — when you want another program (ScaiForge, your own harness) to drive ScaiFlux the way you just did manually.
  • Try a harder task. "Read this 500-line Python file and add type hints," "Convert this JSON schema to a Pydantic model," "Find and fix the bug in parser.py — the tests fail on unicode." The shape stays the same; ScaiFlux scales up with permission modes and context-window management.

Troubleshooting#

  • Model asked clarifying questions instead of writing the code. That's surprisingly persistent for some models; you can nudge with "just go ahead and write it, you can refactor later" or switch to a more action-oriented model via /model <slug>.
  • Permission prompt fired in the middle of a turn. You're in prompt mode rather than workspace-write. init defaults to workspace-write, but you may have changed it via /mode. Run /mode workspace-write to relax.
  • No git for the commit step. Either install git, or skip Turn 5 — it's optional.
  • Tests took multiple iterations to pass. That's normal and shows the loop working. If it stalls (same error twice), the task may be too ambiguous for the model — break it into smaller sub-asks.
Updated 2026-05-18 14:34:13 View source (.md) rev 2