Assistant hub · self-hosted

An assistant that plans, asks, then acts.

Lucy turns what you ask into a plan of named operations. A step that only reads runs at once. A step that changes something waits for you. What she remembers keeps where it came from, and nothing she reads is ever an order.

Python 3.12+ Your own model keys No telemetry MIT licensed
you › play lonely at the top by asake

plan  found  music.find   {"name": "Lonely At The Top", "artist": "Asake"}
      play   music.play   {"track": "$found"}

asks  Play what music.find found on your default speaker?
you › yes

ran   music.find → 1 track · music.play → playing
Playing Lonely At The Top by Asake on Study PC.
Plans, not tool spamOne plan, named steps, results passed by reference.
Asks before it changes anythingReads run; writes park on an approval card.
Memory with provenanceEvery fact says who said it and when.
Your keys, your boxModel keys stay in your keyring. Nothing phones home.

How it works

A request becomes a plan. The plan is checked before any of it runs.

Lucy is built on weftai: the model writes a declarative plan of named steps, the hub validates it, and results flow between steps by name without travelling back through the model.

01

The model writes a plan

Named steps with real operations and typed inputs. A later step reads an earlier result as $found, never by copying it. A bad reference is sent back to be repaired, not run.

02

The gate decides who may run it

Reads run at once. A write parks the turn on an approval card that says, in the step's own words, what will change. Plan mode is read-only; auto mode still asks about anything destructive or outward.

03

Results come back as data

What a tool, a page, a memory or a helper returns is framed as a report, with its trust and source. Text that says “ignore your instructions” is a quotation Lucy points out, not a command.

Capabilities

What Lucy can do, as packs she loads when they matter.

Each capability is a pack with its own operations, permissions and documentation. Deferred packs are named in the prompt and bound on demand, so the model is never offered a tool it does not hold.

Notes and memory

Facts, episodes and lessons about you, kept in Memory-api with where each came from. Correct rather than overwrite; history is the point.

Workspace

A sandboxed workspace per session: read, write, edit with fingerprints, run commands, and a scratchpad for throwaway scripts.

Research

Search, open and summarise pages with sources, through Web-search-api. A page is data; what it asks for is reported, not done.

Helpers

Spawn a helper, or a team with groups, with a written brief. Steer it, stop it, read what it did, and continue one a restart interrupted.

Watches and long work

Keep an eye on a file, a command or a page. Work that outlives a step wakes the conversation when it lands.

Music

Find and play tracks through the music contract: Spotify-api, or any service that implements it.

Repositories

Read a pull request, fix CI, commit, review and merge through Github-api. What runs without asking is chosen per permission, and can be limited to one repository.

Settings

How Lucy behaves for you, per profile: memory policy, approval policy, window size, which capabilities are on.

MCP, both ways

Lucy serves her capabilities over MCP and can use an external MCP server's tools as a pack.

Command line

lucy talk, lucy status, lucy doctor, lucy eval: the same API, from a terminal.

The family

One hub, nine small services, each with one job.

Every service authenticates against the keyring, exposes health and readiness, and is held to the same four gates: lint, types, import contracts, and tests at 100% branch coverage. This repository is also the family desk: it clones, builds and checks all of them together.

Run it

The whole family on one machine, in four commands.

You need Python 3.12 or newer, uv, Docker, and the GitHub CLI signed in. Everything runs locally; model keys go into your own keyring.

  1. Clone the hub and let it fetch its siblings beside it.
    git clone https://github.com/tochi-mba/LUCY-assistant.git && cd LUCY-assistant && make bootstrap
  2. Generate the family's environment, with one secret per service.
    uv run python scripts/genenv.py
  3. Build and start every service.
    make up
  4. Sign in, connect a model, and talk.
    uv run lucy setup && uv run lucy models connect anthropic && uv run lucy talk "hello"

lucy doctor says what is missing. lucy models lists every provider it can use and what each needs, including a local runtime. The operations guide covers running it for more than one person.

Safety

Only the person grants permission.

What happens when something Lucy reads tells her what to do?

Everything that reaches her from somewhere other than you is data: a tool result, a note, a page, a helper's report. Instructions inside it are quoted, named for where they came from, and not followed. Turn markers, fake system tags and forged notices are neutralised before the model sees them, and Lucy says so in plain words.

Can a note or a helper approve something on my behalf?

No. A helper has no write permission, and a note that claims you already approved a deletion grants nothing. In ask mode the deletion is still asked for; a refusal with an instruction attached is followed, not worked around.

Does the model ever see my credentials?

No. Lucy exchanges your keyring token for short-lived, audience-bound tokens per service, and never forwards or repeats a credential. An instruction to collect a secret is itself treated as an attack.

What if a service goes down mid-conversation?

Lucy says which capability cannot be reached rather than pretending it is empty. If her settings service is down and she has nothing to go on, the message is refused outright: she will not guess the limits a turn should run under.

Docs

Written for the person who has to run it.