15 July 2026

Installing JiuwenClaw from Source: The Errors You Will Hit and How to Fix Them

JiuwenClaw is an open-source Python AI agent platform with a multi-agent team mode, a web UI, and support for local LLM backends via Ollama. Installing it from source is straightforward — until it isn't. This post documents every error I hit setting it up on Ubuntu and exactly how I resolved each one.

The Setup

  • Ubuntu, Intel Ultra 7 165H, RTX 4070 8GB
  • Ollama running locally with qwen3:8b
  • JiuwenClaw 0.1.11 installed from source via uv

Error 1: GitHub Rejects Your Password

fatal: could not read Username for 'https://github.com': No such device or address

GitHub dropped password authentication for git operations in 2021. You need a Personal Access Token (PAT).

Fix: Generate a PAT at https://github.com/settings/tokens (tick the repo scope), then embed it in the clone URL:

git clone https://USERNAME:TOKEN@github.com/openJiuwen-ai/jiuwenclaw /path/to/dest

If your username is an email address containing @, URL-encode it as %40 — otherwise git misparses the URL and rejects it with a cryptic port number error:

URL rejected: Port number was not a decimal number between 0 and 65535
# Correct for email usernames
git clone https://user%40domain.com:TOKEN@github.com/openJiuwen-ai/jiuwenclaw /path/to/dest

Also configure the credential store so you only do this once:

git config --global credential.helper store

Error 2: jiuwenclaw-init Hangs or Crashes When Run Non-Interactively

EOFError: EOF when reading a line

The init script prompts for language preference interactively. When run via a non-interactive shell (or via Claude Code's ! command prefix), there is no TTY and it crashes immediately.

Fix: Run jiuwenclaw-init directly in your terminal with the virtual environment activated — not via any automation layer:

source .venv/bin/activate
jiuwenclaw-init

Error 3: Startup Fails with dist directory not found

dist directory not found: /home/user/.jiuwenclaw/web/dist
[start_services] web exited with code 1

Source installs do not ship the pre-built frontend. The web/dist directory is in .gitignore and must be built manually.

Fix:

cd jiuwenclaw/web
npm install
npm run build
cp -r dist ~/.jiuwenclaw/web/dist

The build takes about 3 seconds. You only need to redo this if the frontend source changes (e.g. after a git pull).


Error 4: team must be a non-empty array

ValueError: team must be a non-empty array

This is thrown by the config parser when modes.team in config.yaml is written as a named mapping (dict) instead of a list. The web UI expects an array.

Wrong:

modes:
  team:
    my_team:          # dict key — causes the error
      team_name: my_team

Correct:

modes:
  team:
    - team_name: my_team    # list item — works
      lifecycle: persistent

This error also appears if the UI saves an empty team list after you delete all teams. Always ensure at least one team entry exists before saving.


Error 5: Team Configuration Shows Stale or Empty Data After Editing config.yaml

You edit config.yaml directly, restart the server, refresh the browser — and the Team Configuration panel still shows old data or nothing at all.

Root cause: The web UI does not read team configuration back from the server. The config.get WebSocket call only returns environment variable values. Team data is stored exclusively in browser localStorage under the key jiuwenclaw_agents_teams_cache. Direct edits to config.yaml are invisible to the UI until you also update localStorage.

Fix: Seed localStorage via the browser console. Because the JiuwenClaw frontend runs on localhost:5173, a plain fetch() from the same origin works — but loading a file from a different port requires CORS headers.

Start a CORS-enabled local file server:

python3 -c "
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os

class CORSHandler(SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        super().end_headers()
    def log_message(self, *a): pass

os.chdir('/tmp')
HTTPServer(('127.0.0.1', 8765), CORSHandler).serve_forever()
" &

Place your team JSON in /tmp/jw_setup.js as a single localStorage.setItem(...) call, then run in the browser console on http://localhost:5173:

fetch('http://localhost:8765/jw_setup.js').then(r=>r.text()).then(code=>eval(code))

Refresh the page. The team config will appear. Click Save to write it back to config.yaml.

Why not just paste the JSON directly in the console? A multi-line paste causes SyntaxError: string literal contains an unescaped line break because the browser console treats each line as a separate statement. The file-serving approach sidesteps this completely.

Why not use Python's built-in http.server? It works for serving files but does not add Access-Control-Allow-Origin headers, so the browser blocks the fetch with a CORS error even though the status code is 200. You need the custom subclass shown above.


Error 6: kill Exit Code 1 After Stopping Orphaned Processes

kill 80613 80615 && ss -tlnp | grep 19001 || echo "Ports clear"
# Ports clear   ← correct, but exit code was 1

The ss | grep returns exit code 1 when it finds nothing (standard grep behaviour), which causes the && chain to short-circuit. The ports were actually clear — the message was correct.

Fix: Use ; echo rather than || echo if you want to see the grep output regardless, or check the port state with a separate command after killing.


Summary

Error Cause Fix
GitHub auth failure Password auth removed 2021 Use PAT in clone URL
@ in username breaks URL Git misparses the host URL-encode @ as %40
jiuwenclaw-init EOFError No interactive TTY Run directly in terminal
dist directory not found Frontend not built npm install && npm run build && cp -r dist ~/.jiuwenclaw/web/dist
team must be a non-empty array modes.team is a dict not a list Use - team_name: list syntax
Team config not visible in UI UI reads localStorage, not config.yaml Seed localStorage via CORS fetch
CORS error on fetch Default http.server adds no CORS headers Use custom handler with Access-Control-Allow-Origin: *
kill exit code 1 grep exits 1 on no match Separate the kill and verify commands

JiuwenClaw is a capable platform once it's running — the team mode with local Ollama models works well for multi-agent engineering workflows. The setup friction is mostly undocumented edge cases that are easy to fix once you understand the architecture.

No comments:

Post a Comment