Version-aware task execution agent with long-term muscle memory layer
  • TypeScript 99.9%
Find a file
2026-03-15 21:34:37 +00:00
.zed v0.0.1 2026-02-28 01:17:03 +01:00
docs tools: add docs 2026-03-13 08:56:28 +01:00
example tools: add docs 2026-03-13 08:56:28 +01:00
src tools: add docs 2026-03-13 08:56:28 +01:00
tests tools: add docs 2026-03-13 08:56:28 +01:00
.gitattributes attributes 2026-02-28 04:13:01 +01:00
.gitignore v0.1.1 2026-02-28 03:54:58 +01:00
.npmrc wip: distributed worker & mcp 2026-03-06 20:57:36 +01:00
AGENTS.md v0.1.3: mcp server 2026-02-28 17:07:41 +01:00
deno.json mcp: setup scripts, agent templates, new commands 2026-03-08 22:44:37 +01:00
docker-compose.worker.yml fix: docker mounts 2026-03-09 17:38:28 +01:00
install.ts mcp: setup scripts, agent templates, new commands 2026-03-08 22:44:37 +01:00
main.ts tools: add docs 2026-03-13 08:56:28 +01:00
README.md Update README.md 2026-03-15 21:34:37 +00:00

Vish

A task execution orchestrator and agent.

To achieve goals vish agent writes playbooks and uses them as muscle memory. Instead of reapiting bash commands on every turn it finds appropriate playbooks and actions reusing past experience.

Note

Very soon, the vish agent will become a plugin for vigent. I am moving from OpenCode to more flexible agent and NeoVim-based interface

The Playbooks

The playbook concept and approach to the orchestrastration is borrowed from Ansible. In essence a playbook is a solution - an execution algorithm like script o set of scripts. The agent creates and maintains playbooks to avoid coding solutions from scratch or repeating the same actions in each agent loop.

Memory Layers

  1. Muscle Memory - VISH uses hybrid retrieval. The vector (semantic) search and keyword search in the playbooks and actions index. The retrived results serve as both prompt augmentation and actionable items when applicable.

  2. Long Term Memory - the agent records experience, solved challenges, factual inforamtion into the memory index. The memory index is shared among projects and agent sessions.

  3. Long Term Memory - the agent records experience, solved challenges, factual inforamtion into the memory index. The memory index is shared among projects.

Retrieval Architecture

Depending on which model used and other factors, the long term memory layer may not be used. The decisidion whether to remebeber or not is delegated to the agent.

┌────────<  VISH AGENT  <─────────┐  
│                                 │  
│                                 │  
│     ┌────  PLAYBOOKS ────┐      │  
│     │   (muscle memory)  │      │  
└>IN >──────────────────────>OUT>─┘  
      │  (longterm memory) │         
      └────MEMORY LAYER────┘

Steering Bias

Even with small models like GPT-OSS 20B, the agent behaves well when we mention playbooks directly, or when desired outcome is well defined and matches playbook descriptions.

However, small models have a tendency to start writing code even when there is a solution in context. One of the solutions is to change the embeddings model. A better solution is to provide short, clear instructions instad of abstract goals.

Writing Playbooks

  • Use large models to write and debug new playbooks (GLM-5 is recommended)
  • If you are able to communicate exact instructions in short but complete sentences then even small local models do well.
  • If you have more complex, abstract tasks its better to use large models.
  • Small/Local: GPT-OSS 20b
  • Large/External: GLM-5

Install

deno run -A https://vski.sh/x/vish/raw/main/install.ts

Or build from source:

git clone https://vski.sh/x/vish.git
cd vish
deno task build  # creates ./vish

Quick Start

# Bootstrap a new project
vish create project my-infra
cd my-infra
vish create playbook deploy
vish create action pull playbooks/deploy

# Run actions
vish prod1 deploy pull            # Run action on server
vish group:production deploy pull # Run on server group
vish prod1 deploy pull --dry-run  # Preview commands
vish prod1 deploy pull --docker   # Test in Docker container
vish test --docker                # Run all tests in Docker

Project Structure

project/
├── .vish.yaml           # project config
├── .env                 # environment variables
├── .vish.secrets.yaml   # encrypted secrets
├── test.Dockerfile      # custom Docker image for testing (optional)
└── playbooks/
    └── deploy/
        ├── .vish.yaml   # playbook config (optional dependencies)
        ├── check.yaml
        ├── pull.yaml
        ├── build.yaml
        ├── restart.yaml
        └── scripts/     # uploaded files (optional)
            └── build.sh

Config

.vish.yaml:

servers:
  # Simple format: user@host[:port]
  prod1: root@192.168.1.10
  prod2: root@192.168.1.11

  # Extended format with explicit SSH options
  staging:
    host: staging.example.com
    user: deploy
    port: 2222
    identity_file: ~/.ssh/id_rsa_staging
  bastion:
    host: bastion.example.com
    user: admin
    ssh_options:
      StrictHostKeyChecking: 'no'
      UserKnownHostsFile: /dev/null

groups:
  production: [prod1, prod2]

playbooks:
  - ./playbooks/deploy
  - git@github.com:org/shared-playbooks.git # remote playbook

# Custom Docker image for testing
docker:
  dockerfile: test.Dockerfile
  context: .

Server options:

Field Description
host Hostname or IP address
user SSH username (default: root)
port SSH port (default: 22)
identity_file Path to SSH private key
ssh_options Additional SSH options (key/value)

Docker options:

Field Description
dockerfile Path to custom Dockerfile
context Build context directory (default: .)

Uses ~/.ssh/config as fallback for settings not specified in .vish.yaml.

Actions

playbooks/deploy/pull.yaml:

name: pull
description: Pull latest code
depends_on:
  - check
env:
  BRANCH: main
  GIT_REPO: /var/www/app
command: |
  cd $GIT_REPO
  git pull origin $BRANCH

Env priority: action < .env < CLI --env < secrets

File Uploads

Upload files/directories before action execution:

name: build
description: Build application
files:
  - scripts/*.sh
  - config/*.json
env:
  APP_DIR: /var/www/app
command: |
  chmod +x $VISH_FILES_DIR/scripts/*.sh
  $VISH_FILES_DIR/scripts/build.sh
  • files: Glob patterns relative to playbook directory
  • Uploaded files are available in $VISH_FILES_DIR on the server
  • Directories are created automatically

Dependencies

Define pre-execution checks with auto-fix capability:

name: check
description: Check dependencies
dependencies:
  - check: git --version
    ensure: apk add --no-cache git
  - check: curl --version
    ensure: apk add --no-cache curl
command: echo "All dependencies satisfied"
  • check: Command that exits 0 if dependency exists
  • ensure: Command to install/fix if check fails

Dependencies are verified before actions execute on each server. If check fails, ensure runs automatically, then re-checks.

Playbook-level dependencies can be defined in playbooks/deploy/.vish.yaml:

type: playbook
name: deploy
dependencies:
  - check: which node
    ensure: apk add --no-cache nodejs
actions:
  - ./check.yaml
  - ./build.yaml

Project and playbook dependencies are merged at runtime.

Secrets

vish secrets encrypt   # encrypt .vish.secrets.yaml
vish secrets decrypt   # print decrypted to stdout

Password via VISH_SECRETS_PASSWORD env var.

Auto-encrypt on commit:

vish hooks install

Commands

Command Description
vish create project [path] Create project (default: ./)
vish create playbook <name> [path] Create playbook
vish create action <name> [path] Create action
vish list servers List servers and groups
vish list playbooks List playbooks
vish list actions deploy List actions in playbook
vish sync Pull remote playbooks from git
vish test --docker Run tests in Docker containers
vish hooks install Install pre-commit hook

Bootstrap

Generate project scaffolding with templates:

# Create new project
vish create project ./my-infra

# Create playbook (from project dir)
vish create playbook deploy

# Create action (from playbook dir or with path)
vish create action restart
vish create action build ./playbooks/deploy

Generated templates include commented examples for servers, groups, dependencies, and commands.

Flags

Flag Description
--dry-run Preview without execution
--docker Run in Docker containers
--env KEY=VAL Set env var (repeatable)
--check Check if secrets need encryption
--non-interactive Use env var for password
--json Output JSON events (for piping)

Output

By default, vish outputs human-readable text with colors and status indicators:

▶ Running "pull" on 2 server(s)
  Servers: prod1, prod2

[prod1] connecting...
  → check
  ✓ git --version
  → pull
    Already up to date.
  ✓ pull
[prod1] done

[prod2] connecting...
  → check
  ✓ git --version
  → pull
    Already up to date.
  ✓ pull
[prod2] done

✓ All servers succeeded
  2 succeeded, 0 failed

For scripting or piping to tools like jq, use --json:

vish prod1 deploy pull --json | jq -c .

JSON output (one event per line):

{"type":"run_start","servers":["prod1"],"playbook":"deploy","action":"pull"}
{"type":"server_start","server":"prod1"}
{"type":"ensure_start","server":"prod1","check":"git --version"}
{"type":"ensure_check_pass","server":"prod1","check":"git --version"}
{"type":"action_start","server":"prod1","action":"pull"}
{"type":"stdout","server":"prod1","data":"Already up to date.\n"}
{"type":"action_end","server":"prod1","action":"pull","exitCode":0}
{"type":"server_end","server":"prod1","success":true}
{"type":"run_end","results":{"prod1":{"success":true,"exitCode":0}}}

MCP Server

Vish includes an MCP (Model Context Protocol) server for AI agent integration. This allows AI assistants to execute vish commands and track their status asynchronously.

Starting the Server

vish server --project /path/to/project

The server uses stdio transport, making it compatible with MCP clients like Claude Desktop.

Available Tools

Tool Description
list_servers List all servers and groups in the project
list_playbooks List all available playbooks
list_actions List actions in a specific playbook
execute Execute an action on servers (async)
get_status Get execution status and results
get_logs Get execution logs with pagination
cancel Cancel a running execution

Execution Model

The execute tool returns immediately with an execution_id. Use get_status to poll for completion and get_logs to retrieve output:

// Execute action
{"execution_id": "abc123", "status": "running"}

// Check status
{"execution_id": "abc123", "status": "completed", "success": true}

// Get logs
{"logs": [...], "cursor": "token", "has_more": false}

Claude Desktop Configuration

Add to your Claude Desktop config:

{
  "mcpServers": {
    "vish": {
      "command": "vish",
      "args": ["server", "--project", "/path/to/your/project"]
    }
  }
}