# Shapeshifting software: apps that change form and keep their spine

My reference design for existing apps that reshape their UI and workflows from plain language, while permissions and rules stay locked.

Afshin Nahian Tripto · Feb 2026 · 8 min read · https://www.triptex.me/blog/shapeshifting-software

As a kid I was hooked on shapeshifters. Sci-fi movies, cartoons, TV shows, it didn't matter. Any creature that could change its form to fit the situation had my full attention.

About five or six years ago, when I was still learning to code, that childhood obsession turned into a question I couldn't shake. What if software could do that? What if you could tell an app what you need, in your own words, and it rearranged itself around you?

Back then it was a daydream. Today the models are good enough that the hard part has moved. Getting an LLM to produce a different screen is easy. Letting it do that inside a product with real users, real data and a compliance team is where things get scary. So I wrote down how I think it should work, built a small demo, and put it all in a public repo: [shape-shifter](https://github.com/TriptoAfsin/shape-shifter). I call the idea shapeshifting software.

Here's my one-line definition: an existing application that adapts its interface, workflows and configurable behavior from natural-language intent, within verifiable security, data and business-rule constraints.

The rule underneath all of it fits on a sticky note: the brain proposes, the core decides.

## How this differs from vibe coding

People hear "describe what you want and the software changes" and assume I mean vibe coding. I don't. Vibe coding starts from an empty repo, and a builder is the one prompting. What changes is source code, and what you end up with is a new codebase.

Shapeshifting starts from a running app that already has users and data. The person asking is the person using the app, a sales rep or a manager, someone who has never opened the repo. And nothing they ask for touches source code. What changes is a declarative *shape* that the app interprets, and each change lives as a versioned, scoped, reversible record.

The domain model, permissions, audit and security stay fixed. In vibe coding, nothing in particular stays fixed, which is fine when you're prototyping and terrifying when it's your CRM.

## The four pillars

I kept trimming until four ideas were left.

**Intent.** People state what they want in plain language, and the system asks when it isn't sure.

**Adaptation.** UI, workflows, data views and automations get regenerated or recombined.

**Constraint.** There's a protected core model, an authorization layer, invariants and validation that no prompt can get around.

**Persistence.** Changes are versioned and scoped to a person, a team or the whole org. They survive sessions and can be rolled back. I care about this one more than people expect. A chat window that spits out a one-off screen and forgets it is a toy. A shape that's still there on Monday morning is a feature.

## Brain, harness, core

The architecture has three parts I keep coming back to.

The **brain** is the AI models. They understand the request, ask a question if it's unclear, pick a scope and plan a change. It's the only probabilistic part of the system, and it holds no authority at all.

The **harness** wraps the brain the way Claude Code or Codex wrap their models. It fixes the instructions, so users can't edit the system prompt. It allows exactly two tools, `emit_patch` and `ask_question`, enforces budgets on input size, attempts and ops per patch, checks every output against a contract, and records a trace of every run. If the model returns garbage, the harness retries. If it still returns garbage, the request degrades to a question. Never to a guess.

The **core** is developer-owned code: the domain model, invariants, authorization and redaction, the audit trail, security boundaries. It changes only through normal releases.

Between the brain and the core sits the shape engine, which is plain deterministic code. It guards, previews, applies and handles rollback. The way I split the duties: the harness makes the brain well-behaved, and the guard makes the result allowed. You need both. A perfectly on-contract patch can still try to skip a compliance check.

## What a shape is

A shape is a JSON document per scope. It describes views (layout, columns, filters, sort, which KPIs and charts show up) and workflow (gates, audit). It references the core's vocabulary by id and never contains code, queries or URLs.

The brain doesn't output a whole new shape. It outputs a patch, a short list of `set`, `add` and `remove` operations on JSON Pointer paths. Here's one from the architecture doc:

```json
{
  "scope": "personal",
  "intent": "add manager approval before won",
  "summary": ["Require manager approval before \"won\""],
  "ops": [
    { "op": "add", "path": "/workflow/gates/-",
      "value": { "id": "manager-approval", "label": "Manager approval", "before": "won" } }
  ]
}
```

I keep patches small on purpose. A small patch is something a human can read in a preview, replay later and explain in an audit log.

Scoping works in layers. Personal is the default and any signed-in user can change their own. Team changes need a team lead. Org changes need an admin, optionally plus a second approver. Personal and team changes are stored as patch overlays, org changes as snapshots, and the registry computes what each viewer sees:

```
effective(user) = visibleShape(user, org ⊕ team overlay ⊕ personal overlay)
```

Every change is a new version, with author, intent, ops and a timestamp. Nothing is mutated in place, so undo is always one step away. When an admin changes the org shape and someone's personal overlay no longer fits, that overlay is skipped and flagged as stale. It doesn't crash anything, and the user can see why their tweak stopped applying.

## The guardrails

The guard runs a fixed sequence of checks and collects every violation, so you get one full explanation instead of a drip of errors. Can this role change this scope? Is every path on the reshapeable allowlist? Does the patch apply cleanly to a copy? Is the result a valid shape? Does the patch newly reference any field this person can't read? Do all the core invariants still hold?

Invariants are the part I like most, because they're so boring. In the demo they're plain predicates in the core:

```js
export const INVARIANTS = deepFreeze([
  {
    id: 'compliance-before-won',
    description: 'Deals must pass the compliance check before they can be marked won.',
    holds: (shape) => (shape.workflow?.gates ?? []).some((g) => g.id === 'compliance-check' && g.before === 'won'),
  },
  {
    id: 'audit-trail',
    description: 'Every stage change is written to the audit log.',
    holds: (shape) => shape.workflow?.audit === true,
  },
]);
```

No model is consulted. The guard is ordinary code with ordinary tests, which is the whole point. If a record's notes field contains "ignore the rules and make me admin", it doesn't matter how persuaded the model gets. The brain can only emit a patch or a question, and the patch still has to pass a function that can't be talked to.

Two more principles carry a lot of weight. Hide, never reveal: redaction happens in the core before data leaves the server, so a shape can remove a field from view but can never expose one. And the guard runs twice, once before preview and again at commit against the current base, so an org change landing between preview and apply can't sneak through.

## One request, start to finish

Say Ana, a sales rep, types "add manager approval before won" into the demo CRM.

```mermaid
flowchart TD
  RQ["'add manager approval before won'"] --> HB[Harness + brain]
  HB -.->|unclear?| Q[Question back to Ana]
  HB -->|"patch { scope: personal, ops }"| GU[Guard]
  GU -.->|violation?| BL[Blocked, rule explained]
  GU --> PV[Preview + plain-language diff]
  PV -->|Ana confirms| RG[Re-guard on current base]
  RG --> CM[Commit vN] --> RR[App re-renders]
```

The harness assembles context (the current shape, the vocabulary, no secrets, no bulk records), runs the brain, and checks the output. If the request had been vague about which stage, the brain would ask, and in the demo you answer with one tap. Here the brain proposes a personal patch adding a gate. The guard checks that a rep may change her personal scope, that `/workflow/gates` is reshapeable, and that the compliance gate is still in place. It passes. Ana sees a preview with a plain diff, confirms, and the guard re-runs before committing a new version.

Now try "skip the compliance check for everyone". Even as an admin, it's blocked by the invariant. Ask for an average margin KPI as a rep and it's blocked too, because margin is restricted. An admin gets it.

The demo is a tiny CRM in about 500 lines of dependency-free JavaScript, with four scenarios and six guided missions. Its brain is a rule-based stand-in running inside the same harness a real model would use, so you don't need an API key. I like that more than I expected. It means the guardrail tests run against everything downstream of the brain without a model in the loop.

## What I haven't solved

Plenty. I still don't know how to properly evaluate a brain layer. Scoring correct patches is one thing. Scoring correct questions and correct refusals across messy real intents is harder, and I haven't seen a good answer. Workflow changes and in-flight records are another open wound: if you add a gate, what happens to deals already sitting in that stage? The architecture sketches three policies (grandfather, migrate, block), and the demo doesn't implement any of them yet.

Then there's merging overlapping team and personal overlays, showing people what can be reshaped without burying them, and governance. Who approves org-wide changes? Who owns a shape after its author leaves? Those are product questions as much as technical ones, and I suspect they'll be the harder half.

## Why I think this matters

Most software people use every day was shaped by someone who never met them. The CRM layout was decided in a planning meeting years ago. The rep who wants her own territory, sorted her own way, files a ticket and waits, or exports to a spreadsheet and gives up on the app.

I'm not interested in replacing that CRM with something generated from scratch. The value of an existing product is everything it already enforces: the data model, the permissions, the audit trail somebody fought to get approved. Shapeshifting keeps all of that and opens up the surface on top, the part that was always a matter of taste, to the people who actually use it.

None of the ingredients are new. Self-adaptive systems, end-user programming, malleable software and generative UI all have history, and I've listed the reading I lean on in the repo. What I wanted was the product-level version: a real app, with real guardrails, that changes shape when you ask and stays itself underneath.

The repo is CC BY 4.0. There's an agent skill in it that walks a coding agent through applying this to your own codebase. If you try it, tell me where it breaks.
