Skip to content

Tutorial 1: Your first task

In this tutorial you install malac, connect it to a model, let it fix a small bug while you approve each step, and then review the change and the session.

  1. Install malac.

    curl -fsSL https://raw.githubusercontent.com/lobirus/malac/main/install.sh | sh

    The script ends with the installed version and the next steps:

    Installed malac 1.0.1 to /Users/you/.local/bin

    If it says ~/.local/bin is not on your PATH, add the export line it prints to your shell profile and open a new terminal. Other ways to install are on the Installation page.

  2. Add a provider. If ANTHROPIC_API_KEY or OPENAI_API_KEY is set in your environment, malac already works; skip to the next step. Otherwise add your provider. This example uses an OpenAI-compatible gateway; see Configure a provider for others.

    printf '%s' "$LORA_API_KEY" | malac provider add lora \
    --base-url https://lora.example.com/v1 --model default --api-key-stdin --set-default
    saved provider `lora` to /Users/you/.malac/config.toml
    stored its API key in /Users/you/.malac/credentials.toml
  3. Check the connection.

    malac provider list
    anthropic (anthropic) https://api.anthropic.com · no key
    lora (openai) https://lora.example.com/v1 · key set
    openai (openai) https://api.openai.com/v1 · no key
    default model: lora/default

    The built-in anthropic and openai providers are always listed. malac models asks every provider which models it serves.

  1. Make a small project with a bug.

    mkdir calc && cd calc && git init -q
    cat > calc.py <<'EOF'
    def add(a, b):
    return a - b
    EOF
    git add calc.py && git commit -qm "Add calc"
  2. Ask malac to fix it. This tutorial uses the line mode (--plain) so the output can be shown here; without it, the same run happens in the full-screen terminal UI, with dialogs instead of inline prompts.

    malac --plain calc.py has a bug in add, fix it and verify with a python one-liner

    malac reads the file without asking, because reading is always allowed. Then it wants to edit it:

    ● read calc.py
    ⎿ 1 def add(a, b): (+1 lines)
    ? edit calc.py
    [y] allow [a] always [n] deny
  3. Approve the edit. Press y. malac edits the file and then asks to run the check:

    ? edit calc.py
    [y] allow [a] always [n] deny allowed
    ● edit calc.py
    ⎿ Edited calc.py: (+2 lines)
    ? bash python3 -c "import calc; assert calc.add(2,3)==5; assert calc.add(-1,1)==0; print('ok')"
    [y] allow [a] always [n] deny
  4. Approve the command. Press y again. The check passes and malac reports:

    ● bash python3 -c "import calc; assert calc.add(2,3)==5; assert calc.add(-1,1)==0; print('ok')"
    ⎿ ok
    Fixed `calc.py:2`: `add` returned `a - b`, now returns `a + b`. Verified with `python3 -c "..."` → `ok`.
    ─ lora/default · 3.3k context · 366 out · $0.0024 · 2.2s

    The last line is the turn summary: model, context size, output tokens, cost (when the provider reports it) and time.

  5. Leave the session. In the line mode, malac stays interactive after the first prompt. Type /cost to see the session’s usage, then /exit (or press Ctrl+D).

    › /cost
    input 3312 · cached 0 · output 366 · $0.0024
    › /exit
    the session keeps running in the daemon; `malac --plain` returns to it

    Interactive sessions live in the malac daemon, which started by itself the first time. The session is a tab in your workspace; see Workspaces, tabs and the daemon.

Your wording and steps will differ: models phrase things differently and may check their work another way. What matters is the pattern: read freely, ask before changing anything, verify, report.

  1. Look at the change.

    git diff
    --- a/calc.py
    +++ b/calc.py
    @@ -1,2 +1,2 @@
    def add(a, b):
    - return a - b
    + return a + b
  2. Find the session. Every session is saved as a transcript.

    malac sessions
    019a1f3c-… 2026-10-25 14:02 /Users/you/calc calc.py has a bug in add, fix it and verify with a python one-liner
  3. Read the transcript.

    malac sessions show 019a1f3c-…

    It shows your prompt (›), every tool call (●) with its input, the first line of each result (⎿), the answer, and the session’s token totals. Use the full id from the list.

  4. Continue where you left off. -c continues the most recent session in this directory, with its context:

    malac --plain -c add a unittest for add in test_calc.py and run it

    malac remembers the fix, writes the test, asks to run python3 -m unittest, and reports the result.

Now that you have seen each step, let malac do the same without asking. Put the bug back first:

git checkout calc.py
malac -y -p calc.py has a bug in add, fix it and verify with a python one-liner
● read calc.py
⎿ 1 def add(a, b): (+1 lines)
● edit calc.py
⎿ Edited calc.py: (+2 lines)
● bash python3 -c "import calc; assert calc.add(2,3)==5; assert calc.add(-1,1)==0; print('ok')"
⎿ ok
Fixed `calc.py:2`: `add` returned `a - b`, now returns `a + b`. Verified with `python3 -c "..."` → `ok`.
─ lora/default · 3.3k context · 366 out · $0.0024 · 2.2s

With -y, nothing asks, and -p prints the result and exits instead of staying interactive. Deny rules still apply; Permissions and autopilot explains them, and tutorial 5 sets them up for unattended runs.

  • malac <prompt> starts working right away; --plain uses the line mode, and the default is the full-screen UI.
  • Reading is free; edits and commands ask in ask mode, and -y turns asking off.
  • Every session is saved, can be shown with malac sessions show, and continued with -c.

Next: Delegating to subagents.

malac is created by lobirus and released under the MIT license. About malac