尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證IFS-based agent templating system: interview your inner parts, build evolving profiles, access the Self. Have a seat at the table.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗An agent templating system based on Internal Family Systems (IFS). Interview your inner parts through guided LLM sessions, build evolving written profiles of each part — its qualities, fears, hopes, and relationships to the other parts — and then spawn those parts as AI agents that react to any dataset, document, or decision through their own lens, individually or around a shared table.
This repo ships no specific parts. It ships the flow: the question protocol, the profile schema, the safety rails, and the compilation step that turns a developed profile into a runnable agent. Your parts are yours.
A guide, not a therapist. Sessions are IFS-informed inner work. They can go as deep as a person's parts are willing to go — witnessing an exile, helping it let go of what it carries — but only through its protectors, and never by digging for or suggesting memories. The AI guide is not a therapist or a substitute for one. Read docs/safety.md before you start. If you are in crisis, use a crisis line (988 in the US), not this tool.
IFS (Richard Schwartz) holds that everyone has an inner system of parts — subpersonalities with their own ages, feelings, jobs, and relationships: managers (proactive protectors), firefighters (reactive protectors), and exiles (young hurt parts the protectors shield). Beneath them all is Self — calm, curious, compassionate — the system's natural leader. Every part has a positive intent; there are no bad parts. Longer version: docs/ifs-primer.md.
┌────────────────┐ ongoing ┌────────────────────┐
│ intake session │──────────────▶│ part profile │
│ (meet a part) │ check-ins │ parts/<name>.md │◀── relationship
└────────────────┘ │ (md + YAML, │ mapping
│ grows over time) │ (swarm graph)
└─────────┬──────────┘
readiness gate
▼
┌────────────────────┐
│ compiled agent │
│ part-<name>.md │
└─────────┬──────────┘
your dataset / document / decision
▼
┌────────────────────┐
│ table meeting │
│ each part reacts, │
│ Self synthesizes │
└────────────────────┘
coverage map tracks what's been explored, what's partial, and
what the part has declined — declined topics stay closed. Protectors set
the pace; there is no finish line. As a part comes to trust Self, a
check-in can go further than getting to know it — updating it, meeting what
it protects, helping it let go of something — and the profile records how
the part has changed, not just what it said.The app/ directory is Inner Table, a mobile-first installable
webapp version of this whole flow. Your parts live in your account, so you sign
in to reach them — and find the same parts on any device you sign in on, while
anyone else can sign in on the same device to reach only their own.
Live at ifs-agents.vercel.app (open it on
your phone and Add to Home Screen):
It follows one spine — add a part → gather → integrate → connect:
Add — upload a whole parts/ folder at once, paste raw journaling, or
create by hand with just a name.
Gather — the question bank from
docs/source/ ships in the app. Tap any coverage category to
work through its real IFS questions one per screen, answering, skipping, or
declining — no API key needed. The same bank feeds the AI prompts, and
check-ins target whichever category the profile is thinnest on.
Integrate — answers write straight into the profile's fields. When an AI session closes, its profile is merged, not overwritten, and shown for confirmation first: a thin closing reply can never erase what you already had.
Connect — the swarm map is the editing surface. Every pair of parts is already drawn as a faint thread, because parts sharing a system always relate — you just haven't named it yet. Tap a thread to name it, tap a part to focus its threads, and open the map key to read what every thread style, colour and thickness is saying — and to filter by tone (supportive / in tension / not mapped yet). The key stays closed until asked for, then opens as a sheet on a phone or a side panel on a wider screen, so the map keeps the whole canvas. Edges are written to both profiles, mirrored, with no AI required.
Round the table — a table meeting now ends the way the script does: each part is asked, by name, how it is feeling toward each of the others right now (hostile / wary / neutral / warm / close). Each reading is written to the part that gave it — directed, dated, and never mirrored, because what The Critic feels toward The Dreamer is nothing like what comes back — and the thread between them thickens on the map, a little more with every meeting they sit through. A pair nobody has named yet takes its colour from what they said they felt, so the map answers to a meeting instead of looking identical the morning after one. Parts may pass, and passing records nothing. Meetings you already held can still get their round, from the card on the Table tab — filed on that meeting's date, and never overwriting a more recent reading with an older one. The map key spells the whole scale out, alongside a live count of how many readings the system holds and how many pairs have answered in both directions.
Parts library with coverage rings, type badges, and compile-readiness indicators; swarm map as an interactive touch-draggable graph.
Run it locally with any static server (python -m http.server --directory app,
or npx serve app). There is no build step — app/ is served as static files,
and pushing to main deploys it.
Run the safety tests with node test/run.js — no dependencies, no browser, no
build. They cover data integrity rather than the UI: profile parsing and round
trips, both merge paths, untrusted backups, the question bank, the store, and
mic turn-taking.
Parts live in your account, not on the device. You sign in to reach them, and a part edited on your phone shows up on your desktop; sign out and the account's parts close, so anyone else can sign in on the same device and see only their own. The server side needs three environment variables on the Vercel project:
| Variable | Where it comes from |
|---|---|
UPSTASH_REDIS_REST_URL | your Upstash Redis database |
UPSTASH_REDIS_REST_TOKEN | same |
SESSION_SECRET | any long random string — openssl rand -base64 32 |
A new account opens on three example parts rather than an empty app — a critical manager, an ashamed exile, and a substance-using firefighter, already mapped in the shape those three usually take: both protectors standing in front of the same exile, polarized with each other. They are labelled as examples and sit deliberately short of the compile-readiness bar; rename them, rewrite them, or delete them. They are only ever seeded into an empty account, so signing up after using the app on a device never drops strangers among your own parts.
Accounts are created in the app itself — Create an account on the sign-in screen takes a username and a password of at least 8 characters. A name that already exists is refused rather than overwritten. Each account's parts are stored under its own key and are never readable by another account.
Anyone who can reach the URL can create an account, so treat the deployment as public. To make an account yourself instead — or to reset a forgotten password — run, from the project root:
node scripts/add-user.js <username>
That needs UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN in a local
.env.local (copy them from the Upstash console — Vercel cannot pull back
values marked Sensitive). The password is typed at a prompt rather than passed
as an argument, so it never lands in shell history.
Each user's parts live under their own key and are never readable by another
account. The Upstash token stays server-side in api/; the browser
only ever holds a signed session token. This is a personal inner-work tool, not
a clinical record system — the safety guide applies doubly
once profiles are on a server.
For whoever runs a deployment, the app counts how many people come back, and nothing else. A day counts when a signed-in account opens the app; the server keeps, per UTC day, a list of pseudonymous ids (an HMAC of the username, never the name), plus the day each account was made. Nothing about what anyone writes is recorded, there is no third-party analytics, and signed-out use is not counted at all. Day lists expire after 150 days.
The totals - who came back this week, who is new, how many came back within a week of their first day, weekly cohorts - appear in Settings → Usage, only for the accounts you name:
| Variable | Where it comes from |
|---|---|
STATS_USERS | optional - comma-separated usernames allowed to see Usage; to everyone else the section and /api/stats don't exist |
A script can read the same JSON from /api/stats with CRON_SECRET as the
bearer token. Accounts made before counting began count as returning, never
as new.
A signed-in user can turn on notifications for one device at a time, from Settings → Notifications. This uses the Web Push standard, which is why it's tied to an account (the server needs somewhere to keep the subscription) and why, on iOS, it only works once the app is added to the home screen — Safari itself doesn't expose push at all; only the installed, standalone app does. Today this ships as infrastructure plus a Send test button; nothing sends notifications on its own yet.
It needs one more thing on top of the sync variables above — a VAPID key pair, which is how the server proves to browsers' push services that messages really come from this app:
npm install
node scripts/gen-vapid-keys.js
Set the three variables it prints as Vercel env vars:
| Variable | Where it comes from |
|---|---|
VAPID_PUBLIC_KEY | printed by scripts/gen-vapid-keys.js |
VAPID_PRIVATE_KEY | same — keep this one secret |
VAPID_SUBJECT | a mailto: address or the site's https:// URL |
So that nobody has to bring an API key, the app can run sessions on free
AI models through a FreeLLMAPI
gateway you host. FreeLLMAPI routes each request to whichever free-tier
provider (Google AI Studio, Groq, Cerebras, OpenRouter's free models…) still
has room. The gateway's key stays server-side in
api/free-ai.js. Only signed-in accounts can use it, each
up to a daily allowance. It is the only AI set-up the app shows: Settings has
no AI section. Everyone is told once, before their first session on it, where
their words go, and can choose copy-prompt mode instead. Without the gateway
configured, sessions fall back to copy-prompt mode.
| Variable | Where it comes from |
|---|---|
FREELLMAPI_URL | your FreeLLMAPI gateway's HTTPS address |
FREELLMAPI_KEY | its unified key (freellmapi-…) from the gateway's Keys page |
FREELLMAPI_MODEL | optional — the models to try, in order, comma-separated; the gateway's own auto routing is always tried last. auto alone by default |
FREE_AI_DAILY_LIMIT | optional — messages per account per day, 500 by default |
A model too small for a request, or at its per-minute limit, hands the request on to the next one instead of failing the person. Most of the free capacity is in a few providers: a gateway with only Groq's free tier runs out after a request or two a minute, because each session sends the person's whole inner system. docs/free-ai.md says which providers to add.
FreeLLMAPI can't run on Vercel; it needs an always-on host. On Railway that is a few clicks in a browser. docs/free-ai.md walks through it step by step, along with your own server as the other option, choosing providers with your users' privacy in mind, and the limits of free models.
Install as a plugin (or clone and add the skills/ to your project), then from
any project directory:
/part-intake # meet a new part → parts/<name>.md
/part-checkin <name> # short ongoing session; deepens the profile
/part-map # map relationships between two parts + swarm graph
/part-compile <name> # profile → .claude/agents/part-<name>.md
/parts-meeting <path-to-dataset> # all compiled parts react; Self synthesizes
A typical first arc: one intake (10–20 min), two or three check-ins across a couple of weeks, a second part's intake, one mapping session — then your first table meeting over something real (a budget CSV, a job offer, a draft essay).
The templates/ files are self-contained prompts:
| Do this | Paste this into a chat |
|---|---|
| Meet a new part | templates/interview-intake.md — save the profile it produces |
| Continue with a part | templates/interview-checkin.md + the saved profile |
| Map two parts | templates/relationship-mapping.md + both profiles |
| Have a part react to material | templates/embody-part.md + profile + the material |
| Hold a table meeting | templates/table-meeting.md + 2+ profiles + the material |
| Path | What it is |
|---|---|
app/ | Inner Table — the installable mobile webapp (PWA, zero backend) |
app/js/questions.js | The IFS question bank as data — drives both the in-app questionnaire and the AI prompts |
templates/ | The portable prompts — the heart of the system |
schema/part-schema.md | Canonical profile schema, edge types, coverage model, compile-readiness bar |
skills/ | Claude Code slash-command wrappers around the templates |
docs/ifs-primer.md | IFS concepts as used here |
docs/safety.md | Boundaries, when to stop, privacy — read this |
docs/free-ai.md | Hosting the FreeLLMAPI gateway behind the app's free AI |
docs/source/ | The source question set this system was built from |
examples/ | A fully fictional sample part ("The Critic") and its compiled agent |
parts/, sessions/ | Your data — created at use time, gitignored, never shipped |
Part profiles are intimate. parts/, sessions/, and compiled
.claude/agents/part-*.md are gitignored here — keep them out of shared repos,
and remember that anything pasted into a hosted LLM is subject to that
provider's data policies. Details in docs/safety.md.
IFS concepts originate with Richard C. Schwartz and the IFS Institute; the table-meeting format is modeled on George A. Fraser's Dissociative Table Technique (1991, revised 2003). This repo is an independent self-exploration tool and is not affiliated with or endorsed by the IFS Institute.
MIT License — see LICENSE.
Pictures — give any part a face: a photo, a drawing, a screenshot of
whatever you see when you picture it. Tap the portrait at the top of a
profile (or a part's seat on the Table tab), frame it with a drag and a
pinch, and it stands in for the initial everywhere that part appears — the
library, the profile and the relationships on it, the swarm map, the seats
at the Table, meeting cards, the round of the table, and the chat. The
meeting room can have a photo too: a banner across the top of the room card
on the Table tab (tap it to change it), and the first thing that appears when
a meeting begins. Pictures are cropped and shrunk to a small JPEG on the
device before anything is stored, follow your account between devices (on an
endpoint of their own, so photos can never be what stops your profiles
syncing), and are never sent to an AI or written into an exported .md — they
are for you, not for the model.
Live guided sessions (just talk, intake, check-in, mapping, embody, table meeting) as a chat inside the app, with nothing to set up: they run on the app's free AI. Before the first one, the app says once where your words go. If you'd rather not use it, copy-prompt mode hands you the session to paste into any AI chat you already use. There are no API keys or AI settings to manage. People who connected a key or linked Claude, ChatGPT or Gemini before this keep using it, and can disconnect it under Settings → Your own AI.
Voice first: sessions are spoken by default where the browser supports it. The answer to an IFS question arrives in the pause, spoken, long before anyone would type it. The microphone stays open through the reply, so you can cut in mid-sentence the way you would with someone in the room — the voice stops and the floor is yours — and when a reply ends the turn simply passes, with no button. The reply coming back off the speaker is filtered out rather than heard as an interruption. A dot above the composer says whose turn it is: speaking, thinking, listening. Typing works throughout.
Voice setup: Settings → Voice takes an ElevenLabs key and Find my voices lists that account's own voices — professional clones first — so a cloned voice is one tap, not an ID copied by hand. Without a key it uses the browser voice; if ElevenLabs fails mid-session it falls back rather than going silent.
Round-trip markdown: profiles import/export in the exact
parts/<slug>.md format, so the webapp and the Claude Code skills below
interoperate on the same files.
Installable PWA (Add to Home Screen), works offline, dark/light, and a one-tap "ground me" pause with the safety boundaries built in.