bama
BAMA: 모든 Mac 앱을 만들 수 있습니다
구조화된 계획이나 프로그램을 사용해 Claude를 단계별 에이전트로 실행한다
Run Claude as a step-by-step agent using structured plans or programs
AI가 요약 · README에서
스킬TypeScript · HTMLGitHub @LadislavSopko직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
설치형 프로젝트는 배포 도메인 없이도 확인할 수 있습니다. 개인 저장소는 GitHub 로그인으로, 조직 저장소는 위의 저장소 확인 파일로 직접 확인해 주세요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
CVM: Turn Claude into a Systematic Processor
Stop writing fragile AI scripts. Write programs that Claude executes one thought at a time.
CVM is dual-licensed under AGPL-3.0-or-later for open source use and a commercial license for proprietary integration. See COMMERCIAL.md for details.
New: the CVM Plan Protocol (CVM-PP). Write your work as a structured Markdown plan
and CVM drives an AI agent through it, one task at a time — no hand-written CVM program
needed. If a plan is in CVM-PP form, CVM knows how to run it.
→ What it is & how it works · Protocol specificationREADME 전문 보기 ↗Stop writing fragile AI scripts. Write programs that Claude executes one thought at a time.
CVM is dual-licensed under AGPL-3.0-or-later for open source use and a commercial license for proprietary integration. See COMMERCIAL.md for details.
[!IMPORTANT] New: the CVM Plan Protocol (CVM-PP). Write your work as a structured Markdown plan and CVM drives an AI agent through it, one task at a time — no hand-written CVM program needed. If a plan is in CVM-PP form, CVM knows how to run it. → What it is & how it works · Protocol specification
TRADITIONAL SCRIPT
🔘 Gray = Script Operations
flowchart TD
Start([Start]) --> Loop{More files?}
Loop -->|Yes| Call[Call Claude API with process file prompt]
Call --> Response[Get Response]
Response --> Lost[❌ Context Lost]
Lost --> Loop
Loop -->|No| End([End])
Response -.->|Crash| Restart[Start Over From Beginning]
classDef script fill:#e0e0e0,stroke:#666,color:#000
class Start,Loop,Call,Response,Lost,End,Restart script
CVM ARCHITECTURE
🟢 Green = CVM Operations | 🔵 Blue = Claude Actions | 🟡 Yellow = Human Control
flowchart TD
Start([Start]) --> Loop{More files?}
Loop -->|Yes| CC[CC: analyze file]
CC --> Pause((⏸️ PAUSE))
Pause --> Wait[Wait for Claude]
Wait --> GetTask[Claude: getTask]
GetTask --> Process[Claude analyze file]
Process --> Submit[Claude: submitTask]
Submit --> Save[✓ State saved]
Save --> Loop
Loop -->|No| End([End])
Pause -.->|Can inspect| Status[Check Progress]
Submit -.->|Crash| Resume[Resume from here, just going to start]
classDef cvm fill:#d4ffd4,stroke:#090,color:#000
classDef claude fill:#d4d4ff,stroke:#00d,color:#000
classDef human fill:#ffffd4,stroke:#990,color:#000
class Start,Loop,CC,Pause,Wait,Save,End cvm
class GetTask,Process,Submit claude
class Status,Resume human
Without CVM, you manually chain calls. If it crashes, state is lost:
// Fragile, stateless, and hard to inspect
const result1 = await claude.call("Step 1: Analyze this");
const result2 = await claude.call("Step 2: Based on '" + result1 + "', do this");
// If this fails, you have to start over from scratch
With CVM, you write a simple program. The VM manages state:
// Resilient, stateful, and observable
function main() {
const step1 = CC("Step 1: Analyze this");
const step2 = CC("Step 2: Based on '" + step1 + "', do this");
return step2;
}
The magic: CVM saves step1 before moving to step2. You can stop, inspect, and resume anytime.
Requires Node.js 22 or newer.
Save this as counter.ts:
function main() {
var count = 0;
while (count < 5) {
var next = CC("Current number is " + count + ". What's the next number?");
count = +next;
}
return count;
}
Tell Claude: "Run counter.ts with CVM"
What happens:
CC(), CVM pauses and waitscount and continues the loopgraph LR
subgraph "CVM System"
PROGRAM["📜 Program<br/>(Instructions)"]-->|"loaded into"| CVM["🖥️ CVM<br/>(CPU + RAM)"]
CVM-->|"executes until CC()<br/>then halts"| HALT["⏸️ Halted<br/>(Awaiting input)"]
HALT-->|"getTask"| CLAUDE["🧠 Claude<br/>(Driver)"]
CLAUDE-->|"submitTask"| CVM
USER["👤 User<br/>(Observer)"]-."can interact<br/>with Claude".->CLAUDE
end
Traditional scripts treat Claude as a service. CVM treats Claude as the driver.
Unique Architecture Benefits:
Developer Experience:
Use Cases for Developers:
What Makes It Special: The "GPS analogy" from Claude's docs is perfect - developers write the route, but don't have to worry about getting lost in complex flows. The VM guides execution step-by-step, making it ideal for tasks that would otherwise overwhelm AI context windows.
It's particularly elegant for developers who want to build AI-augmented tools without wrestling with prompt engineering and state management complexities.
CC(prompt) doesn't mean "call Claude." It means:
stateDiagram-v2
[*] --> Package: CC(analyze this)
Package --> PAUSE: Create task
PAUSE --> WAIT: Execution stops here
WAIT --> PULL: Claude calls getTask
PULL --> PROCESS: Claude processes
PROCESS --> RESUME: Claude submits result
RESUME --> [*]: Continue with result
state Package {
[*] --> p1: Package prompt
p1 --> p2: Into task object
}
state PAUSE {
[*] --> pause: ⏸️ Program paused
pause --> save: State saved
}
state WAIT {
[*] --> waiting: 🔄 Waiting for Claude
}
It's like yield in Python or await in JavaScript, but for cognitive tasks.
function main() {
var files = fs.listFiles("./docs");
var summaries = []; // State lives safely in CVM
for (const file of files) {
// PAUSE: Ask Claude to summarize this file
var content = CC("Read and summarize: " + file);
summaries.push({ filename: file, summary: content });
// CVM automatically resumes here with content
}
// PAUSE: Ask Claude to create final report
var report = CC("Create report from: " + JSON.stringify(summaries));
return report;
}
flowchart TD
START([Start]) --> LIST[fs.listFiles]
LIST --> INIT[summaries = empty array]
INIT --> LOOP{For each file}
LOOP -->|Has files| CC1[CC: Read and summarize file]
CC1 --> PAUSE1[⏸️ CVM Pauses]
PAUSE1 --> CLAUDE1[Claude pulls task]
CLAUDE1 --> SUMMARY[Claude returns summary]
SUMMARY --> SAVE[Push to summaries array]
SAVE --> LOOP
LOOP -->|No more files| CC2[CC: Create final report]
CC2 --> PAUSE2[⏸️ CVM Pauses]
PAUSE2 --> CLAUDE2[Claude creates report]
CLAUDE2 --> RETURN[Return report]
RETURN --> END([End])
CRASH{{If crash at file 500}} -.-> STATE[(CVM State:<br/>499 summaries<br/>preserved)]
STATE -.-> RESUME[Can resume<br/>from file 500]
CVM turns this into a resilient workflow. If it fails on file 500 of 1000, the first 499 summaries are safely stored in CVM's state.
graph LR
subgraph YourScript["Your Script"]
S1[❌ Stateless]
S2[❌ Fragile]
S3[❌ Opaque]
S4[❌ Rigid]
S1 --> API1[API Call 1]
API1 --> S2
S2 --> API2[API Call 2]
API2 --> S3
S3 --> CRASH[💥 Crash = Start Over]
end
subgraph CVMArch["CVM"]
C1[✅ Stateful]
C2[✅ Resilient]
C3[✅ Observable]
C4[✅ Flexible]
C1 --> TASK1[Task 1]
TASK1 --> STATE1[(State Preserved)]
STATE1 --> TASK2[Task 2]
TASK2 --> STATE2[(State Updated)]
STATE2 --> PAUSE[⏸️ Can Pause/Resume]
end
| Your Script | CVM |
|---|---|
| ❌ Stateless: Each API call starts fresh | ✅ Stateful: All variables persist automatically |
| ❌ Fragile: Crash = start over | ✅ Resilient: State survives, resume anytime |
| ❌ Opaque: Can't see progress | ✅ Observable: Check status anytime |
| ❌ Rigid: Can't intervene | ✅ Flexible: Paused by default at each CC() |
CVM is a passive MCP server. Claude actively drives execution:
sequenceDiagram
participant Claude
participant CVM
participant State as CVM State
Claude->>CVM: load("counter", "...program code...")
CVM->>State: Store program
Claude->>CVM: start("counter", "exec-123")
CVM->>State: Initialize count = 0
loop While count < 5
Claude->>CVM: getTask("exec-123")
CVM-->>Claude: "Current number is 0. What's the next number?"
Claude->>Claude: Process task
Claude->>CVM: submitTask("exec-123", "1")
CVM->>State: count = 1
Note over CVM: Continue loop execution
end
Claude->>CVM: getTask("exec-123")
CVM-->>Claude: "Execution completed with result: 5"
CVM is completely passive - it never initiates anything. Claude drives everything.
The getTask/submitTask interaction shown above follows Claude's Model Context Protocol (MCP). MCP is a specification for building stateful, resilient tools that Claude can operate. CVM acts as an MCP server, which is what allows Claude to actively drive the execution. You don't need to understand MCP to use CVM, but knowing it's built on this standard helps explain its unique, passive architecture.
You might wonder: "How can a TypeScript while loop be paused mid-execution?" The answer is that CVM isn't running your code with Node.js or ts-node. Instead, CVM uses a custom interpreter that:
CC(), saving the complete execution stateThis is why CVM can pause anywhere - it's not running native JavaScript, but carefully interpreting your code instruction by instruction.
CVM's own development is managed through CVM programs! This isn't just dogfooding - it's proof that CVM can handle complex, real-world development workflows:
🔧 Feature Evolution Programs
🏗️ Architecture Refactoring
These programs guide Claude through hundreds of coordinated changes:
Each program breaks down complex tasks into cognitive checkpoints where Claude provides implementation, reviews code, fixes issues, and verifies correctness - all while CVM maintains perfect state across the entire workflow.
You don't have to hand-write a CVM program for every task. CVM speaks the CVM Plan Protocol (CVM-PP): write the work as a structured Markdown plan (mission + an ordered list of atomic blocks), and if the plan is in CVM-PP form, CVM knows how to run it — an AI agent then drives itself through it, one task at a time.
CVM does not execute the work — it sequences it. It turns the plan into a stream of
checkpoints and hands the agent a single task at a time (write this failing test →
implement it → verify each criterion → commit), holding all the loop / retry / resume /
progress state itself. The agent does the actual work and reports back; CVM advances.
This is the same guide-rope idea as CC(), applied to a whole development plan, so an
agent can follow a long plan without keeping it all in its context.
flowchart LR
PLAN["📄 Markdown plan<br/>(mission + blocks)"] -->|parsePlan| UPLAN["🧩 uplan.json<br/>(validated + compiled)"]
UPLAN -->|planexecutor| SEQ["🔁 One task at a time<br/>RED → GREEN → VERIFY → COMMIT"]
SEQ -->|CC checkpoint| AGENT["🧠 AI agent<br/>does the work, reports back"]
AGENT -->|done| SEQ
Two pieces:
parsePlan — validates the plan against the grammar and compiles it to
.cvm/uplan.json. On any violation it fails with precise line N: message errors.planexecutor — walks the blocks, emitting one phase task at a time to the agent
and advancing as each is reported done. Completed blocks are checkpointed to
.cvm/uplan-progress.json, so an interrupted run resumes where it left off.Plans come in two flavours: tddab (test-driven blocks, RED → GREEN → VERIFY → CROSS-CHECK → COMMIT) and step (action blocks, EXECUTE → VERIFY → COMMIT), and
can span a single file or an index file plus multiple sub-files.
CVM-PP is a documented, stable contract. If an AI (or any tool) produces a plan that conforms to the protocol, it is immediately drivable — no conversion needed. The full specification (grammar, validation rules, examples, authoring checklist) lives in docs/PLAN_FORMAT.md and is intended as an interop target for external plan generators.
CVM ships three universal skills — self-contained Markdown guides that let any AI agent author, review, and run CVM-PP plans without the maintainer's bespoke agent setup. Each references docs/PLAN_FORMAT.md as the single source of truth for the format.
parsePlan.parsePlan, then a semantic quality pass.parsePlan → start → getTask/submitTask loop.Copy each skill directory into your project's .claude/skills/ folder:
mkdir -p .claude/skills
cp -r skills/cvm-plan-create .claude/skills/
cp -r skills/cvm-plan-review .claude/skills/
cp -r skills/cvm-plan-execute .claude/skills/
Or symlink them, so they track this repo's updates:
mkdir -p .claude/skills
ln -s "$(pwd)/skills/cvm-plan-create" .claude/skills/cvm-plan-create
ln -s "$(pwd)/skills/cvm-plan-review" .claude/skills/cvm-plan-review
ln -s "$(pwd)/skills/cvm-plan-execute" .claude/skills/cvm-plan-execute
The skills are plain Markdown with YAML frontmatter — agent-agnostic. Other agent
frameworks can ingest the same SKILL.md files directly; nothing about them is specific
to Claude Code beyond the install path above.
Since CVM uses a custom interpreter, it supports a TypeScript-like subset designed for reliability and safety.
| Feature | Example |
|---|---|
| Variables | var name = "CVM"; var version = 1; |
| Basic Types | Strings, Numbers, Booleans, null, undefined |
| Arrays | [1, 2, 3], items.push(4), items[0] |
| Objects | {name: "Claude", age: 2}, obj.name |
| Loops | while (i < 5), for (const item of array) |
| Conditionals | if (x > 10) { ... } else { ... } |
| Operators | +, -, *, /, ===, !==, &&, ` |
import / require statementsasync / await (use CC() instead)new keywordtry...catch blocks (see error handling below)() => {}...const {a, b} = obj`Hello ${name}`| Function | Description |
|---|---|
CC(prompt: string): string | Pauses execution for Claude to process a task |
console.log(...args) | Outputs to CVM console |
fs.listFiles(path, options?) | Lists files in directory (sandboxed) |
JSON.stringify(obj) | Converts object to JSON string |
JSON.parse(str) | Parses JSON string to object |
CVM runs your code in a secure, isolated environment:
fs.listFiles() is limited to the CVM working directoryFor additional security, we recommend running CVM in a Docker container when processing sensitive data.
Since CVM doesn't support try...catch, you must validate Claude's responses defensively:
// ❌ Fragile - assumes Claude returns a number
function fragileCounter() {
var count = 0;
while (count < 5) {
var next = CC("Current number is " + count + ". What's next?");
count = +next; // Fails if Claude returns "four" instead of "4"
}
}
// ✅ Robust - validates the response
function robustCounter() {
var count = 0;
while (count < 5) {
var result = CC("Current number is " + count + ". What's next?");
var nextNum = parseInt(result, 10);
if (isNaN(nextNum)) {
console.log("Invalid response: '" + result + "'. Retrying...");
// Loop continues without incrementing, effectively retrying
} else {
count = nextNum;
}
}
return count;
}
You can inspect any running execution using the status tool:
// Claude can check status at any time:
const status = await cvm.status("exec-123");
console.log(status);
// {
// "executionId": "exec-123",
// "status": "PAUSED",
// "currentTask": "Analyzing file 247 of 1000",
// "state": {
// "filesProcessed": 246,
// "summaries": [...]
// }
// }
This allows you to monitor long-running tasks and verify progress without interrupting execution.
MCP Tools Claude Uses:
load(programId, source) - Load a programstart(programId, executionId) - Start executiongetTask(executionId) - Pull next tasksubmitTask(executionId, result) - Submit resultstatus(executionId) - Check state anytimeparsePlan(filePath) - Validate a CVM-PP plan and compile it to .cvm/uplan.json (see The CVM Plan Protocol)What CVM Maintains:
Add to Claude's MCP settings:
{
"mcpServers": {
"cvm": {
"command": "npx",
"args": ["cvm-server@latest"]
}
}
}
Perfect for any workflow where Claude needs to process many items systematically:
→ Full API Documentation → CVM Plan Protocol (CVM-PP) Specification
CVM doesn't make Claude smarter. It makes Claude systematic.
Without CVM: Brilliant but chaotic With CVM: Brilliant with perfect memory and a checklist
CVM is dual-licensed:
If you are a company that wants to integrate CVM into a commercial product, ship it inside a closed-source tool, or expose it as part of a hosted service without releasing your own code under AGPL, see COMMERCIAL.md.
Note on previous versions: All releases up to and including version
0.16.0-next.8were licensed under Apache-2.0 and remain available under those terms. Starting from version1.0.0, CVM is dual-licensed as described above.
Copyright (C) 2025-2026 Ladislav Sopko.