ACRYL ownMyAI · Vienna · 20 October 2026 · RSVP on Luma
Own Your AI #5 · Tuesday 20 October 2026, 18:00 to 21:00 · IT-Services der Sozialversicherung, Johann-Böhm-Platz 1, 1020 Wien · luma.com/2mxma8s0

Agentic apps from day one

ACRYL is an agentic IDE that writes its own plugins while it runs. It is built with ACRYL Blends, an open framework where any app, from an IDE to a drum machine, is a set of plugins with an agent inside that operates it and grows it.

95features built
~90 sfrom sentence to live plugin
3operating systems
MITon GitHub and npm
acryl.dev · github.com/acryldev/acryl · acrylblends.github.io · cordisplugins.github.io
The mission

A new kind of software: composable software 2.0, agentic from day one

It writes itself

Ask for a feature and the agent inside builds it as a plugin, live, while you keep working.

It repairs itself

The agent tests what it built, finds what is wrong and fixes it; a broken plugin is reverted without a trace.

It adapts to its use

Two people start from the same app and end up with two different apps, each shaped by how they work.

It is made of parts

Small plugins you can add, swap, remove, version, share and reuse, so nothing is rebuilt from zero.

And it is yours: it runs on your machine, with your data, from files you can commit to your own git.

Why now: the SaaSpocalypse

When agents write code, any product that is not agentic can be copied, rebuilt cheaper, or open-sourced.

Features are no longer a moat

A competitor's agent rebuilds your feature list in a weekend.

Fixed software ages instantly

Every user wants it slightly different; a fixed product serves the average user, and no one exactly.

What stays valuable

Software that keeps evolving with each user, with an agent inside that knows the app and grows it.

The foundation

Cordis: the plugin kernel under DeepSeek Harness and ACRYL

Cordis began as the plugin kernel of Koishi, a cross-platform chatbot framework (Discord, Telegram, Matrix and more) with more than 4,000 community plugins. It was extracted in 2022 as a meta-framework that knows nothing about LLMs, agents or tools. DeepSeek Harness forked it as @deepseek-ai/cordis and built the whole agent as Cordis plugins: model adapters, tools, sessions, sandboxes, storage and the interface. The design is described in the paper A Programming Paradigm for Spatiotemporal Composability (Peking University and DeepSeek-AI).

Why it exists: the session outlives its parts

A group chat or a coding session runs for days while its capabilities arrive, leave and get replaced. Cordis gives two guarantees so that never breaks the session.

Temporal composability

When a component leaves, everything it did to the shared environment is reverted: routes, tools, timers, subscriptions. No residue, and unrelated work survives.

Spatial composability

Components declare what they need. A consumer activates only when its requirements exist, keeps a stable resolution while running, and stops before its provider is withdrawn.

component = requirements + provisions + effects with undo

How it works

Plugina definition:name, inject, apply()ctx.plugin()Fiberone mounted, live instancelifecycle stateits own child Contexteffect disposersdependency snapshotchild FibersownsContext (ctx)what the plugin can see and change· resolves services by name· owns effects, listeners, plugins· dispatches typed events· carries scope: isolate, interceptOne plugin can be mounted many times: each mount is its own Fiber with its own Context.

A plugin definition, mounted with ctx.plugin(), becomes a Fiber; the Fiber owns its Context, its effects and its child Fibers.

PartWhat it is
ContextThe scoped environment a plugin receives; services, events and effects live on it.
ServiceA named capability such as ctx.tools or ctx.llm, replaceable by another provider.
injectA live dependency contract: the plugin stays PENDING until every named service exists; a provider change reactivates it.
EffectsEvery registration is owned and has an inverse; unloading runs the inverses in reverse order.
FiberOne mounted plugin instance: PENDING, LOADING, ACTIVE, FAILED, UNLOADING, DISPOSED.
LoaderRows in cordis.patch.yml become the live plugin tree; change a row and the tree updates.
root ctxtools · llm · shellplugin ctxextend(): inherits allyour pluginctx.tools worksgroup Aisolate('shell')group Bisolate('shell')LocalShelltimeout 5 sLocalShelltimeout 60 sagent Actx.shell = A'sagent Bctx.shell = B's

Context: each plugin sees the world through its own ctx; isolate gives two groups their own provider of the same service name.

PENDINGwaiting for injectdeps readyLOADINGapply(ctx) runsapply() finishedACTIVEeffects ownedapply or config errorFAILEDerror reportedprovider changed, restart, updateUNLOADINGeffects revertedrequirements gone: back to waitingstill met: new episodedispose()DISPOSEDremoved for good

Fiber lifecycle. PENDING is not an error: the plugin is mounted and waiting for what it injects.

ctx.llma named servicellm providerDeepSeek adapterprovidessummarizerinject: ['llm']chat agentinject: ['llm']resolvesresolvesllm provideranother model, replacing itswap inReplace the provider: every consumer unloads and reactivates against the new one. No restart, no stale reference.

Services and inject: consumers depend on a name; a replaced provider reactivates them.

emitsync broadcastctxL1L2L3every listener runs now; results ignoredparallelawait all at oncectxL1L2L3all listeners run concurrently; wait for every oneserialfirst answer winsctxL1L2L3returns a value: stopawait each in turn; a value stops the chainbailsame, synchronousctxL1L2L3returns a value: stopfirst non-empty value is the resultwaterfallwraps a defaultctxL1L2default handlereach listener wraps the next; next() continues

Events: emit, parallel, serial, bail and waterfall.

default handlersends the model requestlistener 2: policyif (blocked) return 'blocked' // vetoreturn next()listener 1: loggerlog(request); return next()requestresult

Waterfall: each listener wraps the next; next() continues, returning without it answers or vetoes.

every registration is an effect with an inverselisteners, tools, routes, services, child plugins1tool summarize registered2route GET /summary mounted3timer every 60 s startedapply(): 1, 2, 3unload: 3, 2, 1

Effects: registered 1, 2, 3; reverted 3, 2, 1 when the plugin unloads.

cordis.patch.yml- id: brand name: acryl-brand config: { name: Music }- id: acryl-music name: acryl-music- id: workspace name: acryl-workspaceLoaderapp rootone ContextbrandFiber · ACTIVEacryl-musicFiber · ACTIVEworkspaceFiber · ACTIVEChange one row's config: only that Fiber reloads.Remove a row: its Fiber unloads and reverts its effects.

Loader: rows of cordis.patch.yml become the live tree of Fibers.

// a Cordis plugin, simplified: needs the tools service, adds one tool
export const name = 'word-count'
export const inject = ['tools']

export function apply(ctx) {
  ctx.tools.register(defineTool({
    name: 'word_count',
    description: 'Count words in a text',
    parameters: { text: { type: 'string' } },
    async execute({ text }) { return text.split(/\s+/).filter(Boolean).length },
  }))
  // unloading the plugin unregisters the tool: no cleanup code
}

What Cordis does not do

Cordis composes a running process. It does not describe, version or share an app: a profile is a local list of bundles on one machine, nothing pins exact versions and checksums, and there is no registry of whole apps to start from. That gap is why the DeepSeek Harness community already has thousands of plugins that solve the same problems again and again.

On top of Cordis

ACRYL Blends: a protocol for composable software people can share and reuse

Cordiscontext · services · inject · revertible effects · fibers · LoaderDeepSeek Harnessthe agent loop, tools, models, sessions, as Cordis servicesACRYL Blendsmanifest · lock · registries · plugin hub · save to git · acryl new --from · acrylblends CLIyour appsACRYL IDE · GTD · accounting · music · anything, each with an agent inside

The stack, bottom to top.

Your apps

ACRYL IDE, GTD, accounting, music, anything, each with an agent inside.

ACRYL Blends

blend.yaml manifest, blend.lock.json, registries, plugin hub (pull, share, verify), save to git, acryl new --from, the acrylblends CLI.

DeepSeek Harness

The agent loop, tools, models and sessions, as Cordis services.

Cordis

Context, services, inject, revertible effects, fibers, Loader.

An app in one file

kind is a Blueprint to start from, or a Blend grown from one. extends inherits another app's rows so you override only what differs. rows are Cordis plugins and their config, the same rows the Loader runs. @webboxes/blends-core validates it, and the lock pins every plugin by version and checksum.

# registry/blends/acryl.music/blend.yaml (real)
apiVersion: blends.acryl.dev/v1alpha1
kind: Blueprint
metadata:
  id: acryl.music
  name: Music
  version: 0.1.0
  category: creative
  license: MIT
  visibility: public
spec:
  runtime: cordis
  extends: acryl.blank
  rows:
    - id: brand
      name: acryl-brand
      config: { name: Music, tagline: Say the beat, hear the beat. }
    - id: acryl-music
      name: acryl-music

Why we built it: write a piece once, everyone can reuse it

Compose

An app is rows of Cordis plugins. Add, override or remove one without forking anything.

Lock

The lock pins every plugin: a local folder by content hash, npm by integrity, a pulled plugin by source and sha512.

Share

Push a plugin or a whole app to git or a registry, private or public. Others pull it by name, verified.

Reuse and grow

acryl new --from starts from anyone's app; the agent inside adds plugins; a snapshot records it all again.

ACRYL and the open framework run the same packages: @webboxes/blends-core, @webboxes/plugin-hub and @webboxes/app-persistence on npm, MIT.

Architecture

How it all fits together

Above Cordis everything is plugins in rows. An app, the IDE included, is a choice of rows and their config: a Blend.

Cordisthe kernel: Context · services and inject · events · effects with undo · Fibers · LoaderDeepSeek Harnessthe agent as Cordis plugins: agent loop · tools · models · sessions · authorizationACRYL runtimeapp instances and homes · surfaces · agent control (Claude Code, Codex, ACP) · blends-core (manifest, lock, upgrade)core pluginsacryl-*uisystem-promptplugin-context (the builder)plugin-hubapp-savebrandBlendsblend.yaml + lockACRYL IDE+ IDE pluginsGTD+ acryl-gtdAccounting+ acryl-accountingMusic+ acryl-musicyours+ what you needsurfacesDesktopWebTerminalpull a plugin or a Blend by name: registries, npm, gitacrylblends.github.io · cordisplugins.github.ioEvery box above Cordis is plugins in rows. An app is which rows, with which config.

The whole map, from the Cordis kernel to the surfaces.

ACRYL IDE is a Blend

acryl.blankthe same core every app starts fromacryl-uithe shell and its slotsacryl-system-promptwho the agent isacryl-plugin-contextthe builder insideacryl-app-savesave to gitacryl-brandname, colours, logo+ACRYL IDE pluginsrows in the same Loader, nothing specialacryl-app-shellprojects list, tabs, right panelacryl-workspaceprojects, worktrees, terminals, filesacryl-agent-controlClaude Code, Codex, ACP agentsacryl-plugin-hubpull, verify, pin pluginsacryl-plugin-adminturn plugins on and offacryl-settings · acryl-sign-inkeys, accounts+ the plugins you or the agent add<project>/.acryl-plugins/: the Pomodoro timer, the GitHub issues tool/blend snapshotblend.yaml + lock: share your IDE like any appThe IDE is not a special program: it is a Blend with more plugins.

The IDE is the Blank core plus IDE plugins plus your own; /blend snapshot shares it like any app.

Three apps, one shape

acryl.blankbrand · plugin-context (the builder inside) · system-prompt · ui · app-save + acryl-app-shell: the app frameextends:acryl.gtdbrand: GTD Planner, accent #4dabf7+ acryl-gtdindex.js13 tools: gtd_capture,gtd_triage, gtd_next, ...lib/domain.jsGTD ruleslib/store.js.acryl/gtd.jsonclient.jsthe board is the windowacryl.accountingbrand: Accounting, accent #51cf66+ acryl-accountingindex.js6 tools: invoice_create,expense_add, vat_summarylib/domain.jsVAT and totalslib/store.js.acryl/accounting.jsonclient.jsthe books are the windowacryl.musicbrand: Music, accent #b197fc+ acryl-musicindex.js12 tools: music_beats,music_tempo, music_savelib/domain.jspattern ruleslib/store.js.acryl/music.jsonclient.jsthe sequencer is the windowOne shape: tools the agent calls, rules, local data, and its own window with the agent beside it. The agent operates it and extends it.

GTD, Accounting and Music each extend acryl.blank with a brand row and one domain plugin.

Daily IDE

One worktree per idea, any coding agent in it

Projects and worktrees

One tree for projects, git worktrees and plain folders. A new branch gets its own worktree and its own chat.

Every agent as a tab

Claude Code, Codex, Grok, GitHub Copilot, OpenCode, Pi and ACRYL's own agent, next to terminal, browser, editor, diff, board and doc tabs.

Review loop

Comment on a line, send it to the agent, review changes and commit in the right panel.

Shared brief

A context document every agent in the workspace reads, whichever tool it is.

ACRYL with a project, a feature worktree and Claude Code running in it
Claude Code running in the feature/done-flag worktree; the tree shows which agent works on which branch.
Builds itself

Ask for what your workflow lacks; it becomes a plugin, live

The agent writing and installing a Pomodoro plugin; the timer in the session header
The 🍅 25:00 button appears in the header mid-conversation.
Build me a plugin that adds a Pomodoro timer to the top bar: one click starts 25 minutes and shows the time left, another click stops it. Install it so I can use it now.
~90 s button live2 min 45 s whole turn4 files0 restarts

The agent reads ACRYL's plugin documentation, writes the plugin, verifies and installs it, then clicks its own button to test it. In the rehearsal it noticed the button's label changed every second, an accessibility flaw, and fixed it while the timer kept running.

Build a plugin that gives you a tool to list the open issues of any GitHub repository (title, number, labels, age). Install it, then use it to show me the 10 newest open issues of deepseek-ai/deepseek-harness.
2 min 47 s built and used3 files

This time the plugin is a tool for the agent itself, available in every later conversation.

The agent answering with the issue list from its new tool
The new tool's first answer and the files the agent wrote.
you askone sentenceread docsACRYL plugin guidewrite4 small filesverifyacryl_verify_plugininstalllive, no restartself-testclicks its own UIfound a problem: fix and reinstall

How ACRYL builds a plugin while it runs.

package.json

Name, version, what the plugin needs and provides.

index.js

Host side: services and agent tools.

client.js

UI side: fills a slot such as the session header.

cordis.patch.yml

Where the plugin sits in the app's composition.

Agentic apps

Same framework, very different apps

Each app is a Blueprint in the public registry. Its domain is also a set of agent tools, so the agent operates the app in plain language. The app's own window is its UI, with the agent beside it, and it changes while you watch.

acryl.gtd · Getting Things Done

acryl new my-planner --from acryl.gtd
Capture: call the dentist tomorrow, buy a birthday gift for Anna by Friday, and plan the Vienna talk as a project with three next actions. Ask Marco for the venue access, I'm waiting for him.
45 ssix cards land on the board while you watch
The GTD app: the board is the window, the agent beside it has filed six items
The board is the app; the agent files into it.
The Accounting app: Q3 VAT payable 915 euro in the books and in the agent's answer
"Summarize Q3 VAT": the books and the agent agree, 915 euro.

acryl.accounting · invoices, expenses, VAT

acryl new my-books --from acryl.accounting
Add an invoice for ACME, 1200 EUR net, due in 14 days.
4 to 5 s"Which invoices are overdue?" ~5 s"Summarize Q3 VAT" ~5 s

Six agent tools over the app's data. Asking for a CSV export makes the agent write a new plugin with its tests in about two minutes.

acryl.music · a step sequencer

acryl new my-beats --from acryl.music
Make a 128 bpm techno beat.
Slow it down to 90, take the clap out, and save it as Warehouse.
Add a closed hi-hat track to the drum machine: it should show on the page, make a synthesized hi-hat sound, and be playable with the tools like the other tracks.
5 s operate~2.5 min extend
The Music app: the sequencer is the window, slowed to 90 bpm, clap removed, saved as Warehouse
The drum machine is the app: 90 bpm, no clap, saved as Warehouse.

Real ACRYL Blend apps, running

Each made with acryl new --from from the public registry and run isolated with the real model on 2026-10-19.

An app is a Blend

Snapshot an app, clone it, it restores itself

your appmade and pulled/blend snapshotrecords the appblend.yaml + lockversions, checksumsgit or registryprivate or publicacryl new --fromanyone startsnew apppulls pluginsit grows again: the agent adds plugins, you snapshot again

The life of a Blend.

/plugin pull github:inboxxobni/acryl-quick-notes@0.3.0
pulled, checked by sha512, installed
/blend snapshot
blend.yaml and blend.lock.json written
acryl new planner-copy --from ./my-planner
the copy pulls and installs its plugins on first start
{
  "formatVersion": 3,
  "origin": { "id": "app.my-planner", "kind": "Blend" },
  "lineage": { "blueprint": "acryl.gtd", "blueprintVersion": "0.1.0" },
  "parameters": {},
  "modules": [
    { "name": "acryl-quick-notes", "origin": "pulled",
      "version": "0.3.0",
      "spec": "github:inboxxobni/acryl-quick-notes@0.3.0",
      "digest": "sha512-m9bN..." }
  ]
}

The lock records where every plugin came from: a folder inside the app (by content checksum), npm, or a plugin pulled from GitHub (by source and sha512). The same lock format is written by ACRYL and by the acrylblends framework.

Registries

One registry for Blends, one for plugins, read live

Blends reading acrylblends.github.io

Cordis plugins reading cordisplugins.github.io

Both are static indexes on GitHub Pages. acryl.dev/blends and acryl.dev/packages mirror them.

From scratch

A new agentic app in about three seconds

npx acrylblends@0.2.0 init my-agent --agent --yes
cd my-agent && npm install && npm start
my-agent listening on http://127.0.0.1:PORT
curl -X POST $URL/ask -H 'content-type: application/json' -d '{"question":"create route hello /hello Hello"}'
hello: installed, active.
curl $URL/hello
{"text":"Hello"}

The agent adds the route as a plugin while the server runs. Node 22.19 or newer; MIT; on npm and GitHub.

All features

95 features built today, in 13 areas

#FeatureWhereStatus
Platforms

macOS, Windows, Linux · Desktop, Web, terminal

Desktop

Installers for macOS (Apple silicon and Intel), Windows 10 and 11, Ubuntu and Debian (amd64, arm64).

Web

The same app in your browser, served from your machine.

Terminal

A terminal UI and CLI: npm install -g acryl

curl -fsSL https://acryl.dev/install | bash
What's next

What we are building now

  • nextThe Blends page: save, share, and pull another Blend with a diff of every plugin change.
  • nextSoftware factory: see every agent session on the machine and hand off in one click. Moving work between Claude Code, Codex and Pi through the shared workspace brief works today.
  • nextWorkflows that travel with a Blend: one main agent, worker agents in isolated worktrees, spec-driven.
  • nextSettings and workspaces inside a Blend.