{"id":44687909,"url":"https://github.com/calebwin/pgclaw","last_synced_at":"2026-04-04T22:41:47.788Z","repository":{"id":341029504,"uuid":"1156472879","full_name":"calebwin/pgclaw","owner":"calebwin","description":"A \"Clawdbot\" in every row with 400 lines of Postgres SQL","archived":false,"fork":false,"pushed_at":"2026-02-12T17:32:22.000Z","size":52,"stargazers_count":206,"open_issues_count":0,"forks_count":11,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-27T20:55:15.778Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/calebwin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T17:30:08.000Z","updated_at":"2026-02-26T14:00:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/calebwin/pgclaw","commit_stats":null,"previous_names":["calebwin/pgclaw"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/calebwin/pgclaw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calebwin%2Fpgclaw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calebwin%2Fpgclaw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calebwin%2Fpgclaw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calebwin%2Fpgclaw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/calebwin","download_url":"https://codeload.github.com/calebwin/pgclaw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/calebwin%2Fpgclaw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31417764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-15T06:33:12.833Z","updated_at":"2026-04-04T22:41:47.780Z","avatar_url":"https://github.com/calebwin.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# pgclaw\n\n\u003e \"What if I had an AI assistant in every row of my Postgres table?\"\n\nI asked myself this a few weeks back and pgclaw is what I came up with: an open-source Postgres extension that introduces a `claw` data type to instantiate an AI agent - either a simple LLM or an \"OpenClaw\" agent - as a Postgres column.\n\nWith pgclaw, store your AI agents with the rest of your data. Supports:\n* Simple LLM agents and more stateful \"OpenClaw\" agents\n* Any LLM provider via [rig](https://docs.rig.rs): Anthropic, OpenAI, Ollama, Gemini, Groq, Together, DeepSeek, Mistral, Perplexity, Cohere, xAI, OpenRouter, and more\n* A \"Claude Code\" in each row via [claude-agent-sdk](https://crates.io/crates/claude-agent-sdk): agents that can read/write files, run code, and use tools\n* [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres\n* any language with a Postgres client\n\n## Quick Start\n\n**Prerequisites:** Rust toolchain and PostgreSQL 17 dev headers.\n\n```bash\ncargo install cargo-pgrx\ncargo pgrx init --pg17 download\ngit clone https://github.com/calebwin/pgclaw.git\ncd pgclaw\ncargo pgrx install\n```\n\nThen in `postgresql.conf`:\n```\nshared_preload_libraries = 'pgclaw'\npgclaw.api_key = 'sk-ant-...'\npgclaw.database = 'mydb'\n```\n\n### Try it\n\n```sql\nCREATE EXTENSION pgclaw;\n\nCREATE TABLE tickets (\n    id       serial PRIMARY KEY,\n    title    text,\n    body     text,\n    priority text,\n    agent    claw DEFAULT claw('Set priority to low/medium/high/critical based on urgency.')\n);\nSELECT claw_watch('tickets');\n\nINSERT INTO tickets (title, body) VALUES ('Login broken', '500 error on login page');\n-- ~1-2s later: priority = 'critical'\n```\n\n## The `claw` Data Type\n\nA `claw` value binds an LLM agent to a row. Two modes:\n\n**Inline** — just a prompt:\n```sql\nclaw('Summarize this ticket in one sentence.')\nclaw('Classify sentiment.', model =\u003e 'claude-sonnet')\n```\n\n**Agent reference** — points to a reusable agent definition in `claw.agents`:\n```sql\nclaw(agent =\u003e 'ticket-triage')\nclaw(agent =\u003e 'ticket-triage', model =\u003e 'claude-opus')\n```\n\n## Stateful Agents\n\nDefine reusable agents with identity, instructions, and memory:\n\n```sql\nINSERT INTO claw.agents (id, soul, instructions, memory) VALUES (\n    'ticket-triage',\n    'You are a meticulous support ticket classifier.',\n    'Read the ticket. Set priority (low/medium/high/critical) and summary.\n     If unsure, set medium and explain in summary.',\n    '{\"patterns\": []}'\n);\n\nCREATE TABLE tickets (\n    id       serial PRIMARY KEY,\n    title    text,\n    body     text,\n    priority text,\n    summary  text,\n    agent    claw DEFAULT claw(agent =\u003e 'ticket-triage')\n);\nSELECT claw_watch('tickets');\n```\n\nThe agent can update its own memory by including `{\"__memory\": {...}}` in its response.\n\n## Agents with Workspaces (Claude Code)\n\nAgents with a `workspace` field get their own filesystem directory and run via Claude Code:\n\n```sql\nINSERT INTO claw.agents (id, soul, instructions, workspace) VALUES (\n    'engineer',\n    'You are a senior engineer. You write clean, tested code.',\n    'Implement the change. Run tests. Update status to pass/fail.',\n    'auto'\n);\n\nCREATE TABLE tasks (\n    id serial PRIMARY KEY, task text, status text DEFAULT 'pending', diff text,\n    agent claw DEFAULT claw(agent =\u003e 'engineer')\n);\nSELECT claw_watch('tasks');\n```\n\nRequires [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) (`npm install -g @anthropic-ai/claude-code`). Workspace paths: `'auto'` uses `{pgclaw.workspace_dir}/{agent}/{table}/{pk}/`, or use a custom template like `'/data/{agent}/{table}/{pk}'`.\n\n## Channels, Sessions, Heartbeats\n\n```sql\nINSERT INTO claw.agents (id, soul, instructions) VALUES (\n    'support-bot', 'You are the support bot for Acme Inc.', 'Help users with orders.'\n);\nINSERT INTO claw.bindings (channel, agent_id) VALUES ('telegram', 'support-bot');\nINSERT INTO claw.heartbeats (agent_id, every) VALUES ('support-bot', '30 minutes');\n\nSELECT claw.route('telegram', '*', 'user123', NULL, 'My order is late');\n-- Pick up responses from claw.outbox\n```\n\n## Configuration\n\n```\n# Required\npgclaw.api_key = 'sk-ant-...'                      # API key for your provider\npgclaw.database = 'mydb'                            # Database for the background worker\n\n# Optional\npgclaw.api_provider = 'anthropic'                   # see supported providers below\npgclaw.api_url = ''                                 # override API endpoint\npgclaw.default_model = 'claude-sonnet-4-5-20250929' # default model for inline claw values\npgclaw.enabled = true                               # enable/disable processing\npgclaw.workspace_dir = '/tmp/pgclaw/workspaces'     # base dir for Claude Code workspaces\n```\n\n**Supported providers:** `anthropic` (default), `openai`, `ollama`, `gemini`, `groq`, `together`, `deepseek`, `perplexity`, `cohere`, `mistral`, `moonshot`, `openrouter`, `xai`, `hyperbolic`, `mira`, `galadriel`\n\n```\n# OpenAI\npgclaw.api_provider = 'openai'\npgclaw.api_key = 'sk-...'\npgclaw.default_model = 'gpt-4o'\n\n# Ollama (local, no API key needed)\npgclaw.api_provider = 'ollama'\npgclaw.default_model = 'llama3.1'\n\n# OpenAI-compatible (vLLM, LM Studio, etc.)\npgclaw.api_provider = 'openai'\npgclaw.api_url = 'http://localhost:8000/v1'\n```\n\n## How It Works\n\n1. You add a `claw` column to a table and call `claw_watch()`\n2. On INSERT/UPDATE, a Postgres trigger enqueues the row to `claw.queue`\n3. A Postgres background worker polls the queue:\n   - **LLM agents** (no workspace): builds prompt from agent config + row data, calls LLM via [rig](https://docs.rig.rs)\n   - **Claude Code agents** (with workspace): creates a workspace directory with `SOUL.md`, `AGENTS.md`, `context.json`, spawns Claude Code via [claude-agent-sdk](https://crates.io/crates/claude-agent-sdk)\n4. The response is parsed for column updates (JSON `{\"column\": \"value\"}`) and applied back to the row\n5. Conversation history is preserved in `claw.history` for multi-turn interactions\n\n## License\n\nMIT of course!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalebwin%2Fpgclaw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcalebwin%2Fpgclaw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcalebwin%2Fpgclaw/lists"}