# Cas

> CAS — Conversational Agent Shell (Go). Single binary TUI: conversation generates workspaces, you control them directly.

- **Type:** MCP server
- **Install:** `agentstack add mcp-goweft-cas`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [goweft](https://agentstack.voostack.com/s/goweft)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [goweft](https://github.com/goweft)
- **Source:** https://github.com/goweft/cas

## Install

```sh
agentstack add mcp-goweft-cas
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

CAS
Conversational Agent Shell

  A terminal shell where conversation generates workspaces and you control them directly.
  Single static binary &nbsp;·&nbsp; deterministic contracts &nbsp;·&nbsp; streaming &nbsp;·&nbsp; persistent sessions

  The Idea &nbsp;·&nbsp;
  See It Work &nbsp;·&nbsp;
  How It Works &nbsp;·&nbsp;
  Keys &nbsp;·&nbsp;
  Quick Start

  
    
  
  
    
  
  
    
  

---

## The Idea

Most AI tools give you a chat window. You type, the model responds, you copy what you need and paste it somewhere else. The conversation and the artifact are separate things in separate places.

CAS is a different arrangement. Conversation is for **generating** things. Once generated, you **control** them directly.

You say *write a project proposal*. A workspace tab opens alongside the chat — tokens streaming into it as the model generates. When generation ends, you edit it directly, ask CAS to make changes, or both. The AI built the artifact. You wield it.

This resolves a debate in HCI running since 1997. Shneiderman argued that direct manipulation gives users control that delegation never can. Maes argued that agents reduce cognitive load that direct manipulation can't scale to. Both were right. CAS addresses it architecturally:

**Agents generate. Users manipulate.**

---

## See It Work

Tokens stream into the workspace as they are generated. The left panel is persistent conversation. The right panel is the workspace you control directly. Multiple workspaces open as tabs — `[d]` document, `[c]` code, `[l]` list.

---

## How It Works

### Intent detection — zero latency, no LLM call

Every message is classified before any model is invoked:

```
"write a project proposal"       → create workspace (document)
"make a todo list for easter"    → create workspace (list)
"create a python script"         → create workspace (code)
"add a shopping section"         → edit active workspace
"add error handling"             → edit active workspace
"how long should this be?"       → chat reply
"edit it directly"               → chat  ← self-edit exclusion fires first
"close the workspace"            → close active tab
"run it"                         → execute active code workspace
"test this"                      → execute active code workspace
"combine the proposal and checklist" → merge workspaces into new document
```

Pure regex, sub-millisecond. Self-edit phrases are checked before edit patterns so "edit it directly" never triggers an unwanted LLM call.

### Deterministic contracts

Every workspace operation passes through a contract layer before execution:

```go
contract.CheckPreconditions()   // is this operation permitted?
contract.CheckInvariants()      // are all invariants satisfied?
contract.CheckPostconditions()  // did the output meet requirements?
```

Contracts run in Go, external to the model. The model cannot modify, bypass, or reason about them. Any violation fails the operation — fail-closed always. Based on Bertrand Meyer's Design by Contract (1988).

Every LLM call is owned by a named agent (`GenerationAgent`, `EditAgent`, `CombineAgent`, `ChatAgent`, `MCPAgent`, `WebAgent`, `OrchestratorAgent`). Contracts are frozen before the LLM call and checked again after. The shell delegates to agents and has no remaining LLM call sites — it only routes.

`MCPAgent` and `WebAgent` operate under an **autonomy dial** (`suggest` / `confirm` / `run`) that governs whether actions are planned only, executed with confirmation, or executed freely within their workspace scope. The contract enforces that any tool or URL used exists on the bound server or page — the agent cannot reach outside its workspace.

### Three workspace types

| Type | Badge | Model (Ollama) | Model (Anthropic) | Model (Groq) | Model (OpenAI) | Model (OpenRouter) |
|---|---|---|---|---|---|---|
| Document | `[d]` | `qwen3.5:9b` | `claude-sonnet-4-6` | `llama-3.3-70b-versatile` | `gpt-4o` | `meta-llama/llama-3.3-70b-instruct` |
| List | `[l]` | `qwen3.5:9b` | `claude-sonnet-4-6` | `llama-3.3-70b-versatile` | `gpt-4o` | `meta-llama/llama-3.3-70b-instruct` |
| Code | `[c]` | `qwen2.5-coder:7b` | `claude-haiku-4-5-20251001` | `llama-3.3-70b-versatile` | `gpt-4o-mini` | `meta-llama/llama-3.3-70b-instruct` |

### Streaming

A placeholder tab appears immediately on create. Tokens stream into it via a buffered channel feeding one event per Bubble Tea tick. The workspace is live from the first token. No separate loading state.

### Code execution

Say `run it` or `execute` with an active code workspace. CAS detects the language from content (bash, Python, Go, JavaScript, Ruby), writes to a temp file, and executes in a sandboxed subprocess with:

- Process group isolation — timeout kills the entire tree, not just the leader
- Environment restriction — only `PATH` is inherited, no secrets leak
- 30-second default timeout
- stdout and stderr captured and displayed in the chat panel

No LLM call is needed — intent detection routes directly to the runner.

### Plugins

Drop `.lua` files in `~/.cas/plugins/` to add custom commands without recompiling:

```lua
-- ~/.cas/plugins/standup.lua
cas.command("standup", "Daily standup from workspaces", function()
    local ws = cas.workspaces()
    local lines = {}
    for i, w in ipairs(ws) do
        lines[i] = "- " .. w.title .. " (" .. w.type .. ")"
    end
    cas.reply("## Standup\n\n" .. table.concat(lines, "\n"))
end)
```

Type `standup` in the chat and the plugin runs — no LLM call, sub-millisecond.

The Lua VM is sandboxed: no file I/O, no `os.execute`, no network. Plugins interact with CAS through a controlled API: `cas.command()`, `cas.reply()`, `cas.workspaces()`, `cas.active()`.

### Cross-workspace operations

With multiple workspaces open, CAS resolves which one you're addressing by fuzzy-matching title fragments:

```
"update the proposal"            → targets "Project Proposal", not the most recent tab
"add the script code to the report" → edits "Report" with "Script" content as context
"combine the proposal and checklist" → creates a new workspace from both sources
"merge all workspaces"           → synthesizes everything into one document
```

Edits that reference another workspace by name automatically include that workspace's content in the LLM prompt — the model can see both documents when making changes.

### Behavioral learning

A Conductor module observes your usage across sessions and builds `~/.cas/profile.json`:

```json
{
  "ws_types": {"document": 12, "list": 5, "code": 3},
  "doc_types": {"proposal": 4, "report": 3, "note": 2},
  "edit_verbs": {"add": 7, "fix": 2},
  "session_count": 6,
  "workspace_count": 20
}
```

This feeds back into LLM system prompts automatically. More sessions → better context → better output. No configuration required.

### Persistence

SQLite (WAL mode) at `~/.cas/cas.db`. Sessions, workspaces, and conversation history survive restarts. Previous workspaces restore as tabs on next launch. Full version history per workspace enables multi-step undo. Orchestration runs and their per-step inputs/outputs are persisted for a complete audit trail. Schema migrations run automatically via `PRAGMA user_version`.

---

## Keyboard Reference

### Chat panel (default focus)

| Key | Action |
|---|---|
| `Enter` | Send message |
| `Tab` | Switch to workspace panel |
| `←` `→` | Move cursor in input |
| `Home` / `Ctrl+A` | Jump to start of input |
| `End` / `Ctrl+E` | Jump to end of input |
| `Backspace` | Delete character before cursor |
| `Delete` | Delete character after cursor |
| `Ctrl+W` | Delete previous word |
| `Ctrl+K` | Delete to end of line |
| `Ctrl+U` | Delete to start of line |
| `↑` / `↓` | Scroll conversation history |
| `Ctrl+N` | Start a new session |
| `Ctrl+C` | Quit |

### Workspace panel (press `Tab` to focus)

| Key | Action |
|---|---|
| `Tab` | Return to chat panel |
| `Esc` | Return to chat panel |
| `[` / `]` | Previous / next workspace tab |
| `e` | Enter inline edit mode |
| `Ctrl+Z` | Undo last change |
| `Ctrl+E` | Export to `~/cas-exports/` |
| `↑` / `↓` | Scroll workspace content |
| `PgUp` / `PgDn` | Scroll by 10 lines |

### Edit mode (press `e` to enter — amber border)

Full terminal editor via `charmbracelet/bubbles` textarea. All standard cursor movement and editing keys work.

| Key | Action |
|---|---|
| `Esc` | Save and exit edit mode |
| `Ctrl+S` | Save without leaving edit mode |
| `Ctrl+C` | Discard changes and exit |

---

## Architecture

```
internal/
├── intent/      Zero-latency intent detection — regex, no LLM call
├── agent/       Seven named sub-agents, each with a frozen contract
│                GenerationAgent, EditAgent, CombineAgent, ChatAgent,
│                MCPAgent (tool calls), WebAgent (web actions),
│                OrchestratorAgent (multi-workspace coordination)
│                Shell has no remaining LLM call sites — it only routes
├── contract/    Design by Contract enforcement, fail-closed
├── workspace/   Lifecycle: create, update, undo, close, restore
├── shell/       Session manager: ProcessMessage, StreamMessage
├── llm/         Ollama, Anthropic, Groq, OpenAI, OpenRouter — streaming/sync, model routing
├── runner/      Code execution — sandboxed subprocess, timeout, env isolation
├── plugin/      Lua plugin runtime — sandboxed gopher-lua VM
├── mcp/         MCP client — connect, discover tools, call, close (SSE transport)
├── webview/     HTTP fetch + HTML parser — title, headings, links, body text
├── store/       Store interface, SQLiteStore (WAL), MemoryStore
└── conductor/   Behavioral learning — observe, profile, user_context
ui/              Bubble Tea TUI: split panel, tabs, streaming, inline edit
tests/tui/       TUI integration tests (spawn real binary via tmux)
cmd/cas/         Entry point: --db, --memory flags
```

**245 tests** across all packages. **8 TUI integration tests** that spawn the real binary in tmux and interact with it as a user would — catching runtime bugs that unit tests miss.

---

## Quick Start

```bash
git clone https://github.com/goweft/cas.git
cd cas
go build -o cas ./cmd/cas
```

### Local inference — Ollama

```bash
ollama pull qwen3.5:9b
ollama pull qwen2.5-coder:7b
./cas
```

### Cloud — Anthropic API (no GPU required)

```bash
export CAS_PROVIDER=anthropic
export ANTHROPIC_API_KEY=sk-ant-...
./cas
```

### Cloud — Groq (free tier, fastest inference)

```bash
export CAS_PROVIDER=groq
export GROQ_API_KEY=gsk_...
./cas
```

### Cloud — OpenAI

```bash
export CAS_PROVIDER=openai
export OPENAI_API_KEY=sk-...
./cas
```

### Cloud — OpenRouter (access hundreds of models with one key)

```bash
export CAS_PROVIDER=openrouter
export OPENROUTER_API_KEY=sk-or-...
./cas

# Use a specific model via override
CAS_MODEL_CODE=anthropic/claude-3-5-haiku ./cas
```

### List configured providers

```bash
./cas --providers
```

### Ingest an MCP server

```bash
# In chat: connects and opens a workspace with the server's tools listed
ingest https://mcp.linear.app/sse

# Then ask the agent to use a tool:
# "list my open issues"  →  MCPAgent reasons, selects tool, calls it
```

### Browse a web page

```bash
# In chat: fetches the page and opens a workspace with its content
browse https://golang.org

# Then ask the agent to work with it:
# "summarise the main sections"
# "navigate to https://golang.org/doc/install"
# "extract all links"
```

### Coordinate across workspaces

```bash
# With two ingested workspaces open (e.g. Linear + GitHub MCP servers):
# "read the linear issue and open a github PR for it"
# → OrchestratorAgent decomposes into steps, executes each in sequence,
#   passes each step's output as context to the next
```

In confirm mode the TUI pauses before each step and prompts for approval
(`y` proceed / `n` skip / `esc` cancel). Every run and its per-step
inputs and outputs are persisted, so any multi-workspace task is fully
auditable and replayable.

### Reconnect a stale workspace

```bash
# After a restart, mcp/web workspaces show a [!] badge — their live
# session ended but their content was preserved. To restore:
reconnect              # reconnects the first disconnected workspace
reconnect linear       # reconnects a workspace by title
```

### Flags

```
./cas                   # restore last session (default)
./cas --memory          # ephemeral session, no persistence
./cas --db /path/to.db  # custom database path
```

### Override model routing

```bash
CAS_MODEL_CODE=qwen3.5:27b ./cas        # use 27b for code workspaces
CAS_MODEL_DOCUMENT=qwen3:14b ./cas      # use 14b for documents
```

### Tests

```bash
go test ./...

# TUI integration tests — requires tmux + Ollama running
TUI_INTEGRATION=1 go test -v -tags=integration ./tests/tui/ -timeout 300s
```

---

## Export

`Ctrl+E` in workspace focus writes the active tab to `~/cas-exports/`:

- Documents and lists → `.md`
- Code → extension detected from content (`.py`, `.go`, `.sh`, `.js`, `.rb`, `.txt`)

The directory is created automatically if it doesn't exist.

---

## References

Shneiderman & Maes (1997). "Direct Manipulation vs. Interface Agents." *Interactions, 4(6).*

Meyer (1988). *Object-Oriented Software Construction.* Prentice Hall. (Design by Contract)

Norman (1986). "Cognitive Engineering." In *User Centered System Design.*

Horvitz (1999). "Principles of Mixed-Initiative User Interfaces." *CHI '99.*

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [goweft](https://github.com/goweft)
- **Source:** [goweft/cas](https://github.com/goweft/cas)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** yes
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-goweft-cas
- Seller: https://agentstack.voostack.com/s/goweft
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
