{"id":28303719,"url":"https://github.com/9aia/castor","last_synced_at":"2026-04-01T21:50:53.227Z","repository":{"id":291702259,"uuid":"977907447","full_name":"9aia/castor","owner":"9aia","description":"⚗️ CLI tool to connect, explore, and query SQL databases using JavaScript-defined blocks.","archived":false,"fork":false,"pushed_at":"2025-09-17T00:32:27.000Z","size":274,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-27T23:41:53.113Z","etag":null,"topics":["cli","cloudflare","d1","database","developer-tool","gaia-public","open-source","public"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/9aia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"2025-05-05T06:56:43.000Z","updated_at":"2025-09-17T00:32:30.000Z","dependencies_parsed_at":"2025-06-20T02:25:10.119Z","dependency_job_id":"ab042aa1-e9d1-4f91-b429-d4729170dc1f","html_url":"https://github.com/9aia/castor","commit_stats":null,"previous_names":["9aia/castor"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/9aia/castor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9aia%2Fcastor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9aia%2Fcastor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9aia%2Fcastor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9aia%2Fcastor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/9aia","download_url":"https://codeload.github.com/9aia/castor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/9aia%2Fcastor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"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":["cli","cloudflare","d1","database","developer-tool","gaia-public","open-source","public"],"created_at":"2025-05-23T23:11:39.039Z","updated_at":"2026-04-01T21:50:53.198Z","avatar_url":"https://github.com/9aia.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🦫 Castor — Interactive CLI for Database Blocks\n\n**Castor** is a free, open-source, dev-focused database management tool written in Node.js with TypeScript designed for the command line. Think of it as a minimal, scriptable SQL client — built from the ground up for developers who live in the terminal.\n\nIt supports a wide range of databases — like MySQL, PostgreSQL and SQLite — but the current prototype focuses on [Cloudflare D1](https://developers.cloudflare.com/d1/) support.\n\n\u003e [!WARNING]\n\u003e ⚗️ Experimental — This project is in early stages and under active development. Expect rough edges, missing features, and possibly fast iteration.\n\n## Goals\n\n- 📜 Make database querying scriptable and trackable via source code\n- 🔒 Provide type-safe and schema-aware query \"blocks\" (powered by `zod` and `typescript`)\n- ⚡ Load automatically structured query \"blocks\" from `js`/`ts` files\n- 💬 Generate automatically and type-aware prompts in the terminal for input\n- 🗂️ Allow the developer to organize queries in folders, version them, track changes with `git`\n- 💾 Provide first-class support for `Cloudflare D1` (but with support for providing custom adapters)\n\n## Scope\n\nCastor enables you to:\n\n* 🔌 Connect to your database directly from the terminal\n* ✍️ Provide query *block* definition utilities in `.ts`/`.js` files\n* 🧠 Run blocks interactively in the terminal, with input prompts\n\n**Out of scope:**\n\n* ❌ GUI or Web UI\n* ❌ Query editors or ER diagram tools\n* ❌ Export/import utilities\n* ❌ Block versioning or saving queries outside source code (use `git` for that)\n* ❌ Agnostic data validation (use `zod` for now)\n\n## Features\n\n* ✅ Block discovery from file system\n* ✅ Typed CLI prompts using `zod` schemas\n* ✅ `Cloudflare D1` + `drizzle-orm` integration\n* ⚠️ Danger mode prompts\n* 📄 Custom configs\n* 📝 Run with saved or new input\n\n## Installing\n\n\u003e [!WARNING]\n\u003e \u003e Castor requires [`tsx`](https://github.com/esbuild-kit/tsx) to run TypeScript files smoothly in your CLI.  \n\u003e Install it globally or as a dev dependency:  \n\u003e ```bash\n\u003e npm install -g tsx\n\u003e # or\n\u003e npm install -D tsx\n\u003e ```\n\nTo install Castor, use NPM:\n\n```bash\nnpm install -D @9aia/castor\n```\n\nOr with other package managers like PNPM or Yarn!\n\n\u003e [!WARNING]\n\u003e `zod` and `drizzle` are peer dependencies and must be up to date with the version used by this package.\n\n### Adding the database type to Castor\n\nCastor needs to know the type of your database. You can do this by adding a `types.d.ts` file to your project:\n\n```ts\n// types.d.ts\nimport { Database } from '~/lib/db'\n\ndeclare module '@9aia/castor' {\n  interface Register {\n    database: Database\n  }\n}\n\nexport {}\n```\n\n### Adding the Script to your `package.json` (Recommended)\n\nAdd the `db:client` script to your `package.json`:\n\n```jsonc\n// package.json\n{\n  \"scripts\": {\n    \"db:client\": \"castor --config path/to/config.ts\"\n  }\n}\n```\n\n## Documentation\n\n### Configuring\n\nYou can define your own config file using `defineConfig()`:\n\n```ts\n// castor.config.ts\nimport type { Database } from '~/'\nimport { defineConfig } from '@9aia/castor'\n\nexport default defineConfig({\n  rootDir: './db-client', // the directory Castor will explore\n  source: defaultSource =\u003e [...defaultSource, '!**.md'], // exclude MD files\n  drizzle: { // DrizzleOptions\n    logger: true,\n  },\n  dbProvider: 'd1',\n  d1: {\n    binding: 'DB',\n  },\n  wrangler: { // GetPlatformProxyOptions\n    persist: true,\n  },\n})\n```\n\nSupports:\n\n* `d1` binding from Wrangler\n* Custom `dbProvider` function\n* File filters using `fast-glob` patterns\n\n### Defining Sessions\n\nCreate files in `db-client/`, like `user.ts`, and export your query blocks there.\n\n### Defining Blocks\n\nBlocks are typed and named operations. They can query or mutate your database:\n\n```ts\n// ./db-client/user.ts\nimport { block } from '@9aia/castor'\nimport { eq } from 'drizzle-orm'\nimport { z } from 'zod'\nimport { users } from '~/db/schema'\n\nblock('List all users', {\n  query: db =\u003e db.select().from(users)\n})\n\nblock('Get user by id', {\n  schema: z.object({ id: z.string() }),\n  query: (db, input) =\u003e (\n    db.select().from(users).where(eq(users.id, input.id))\n  ),\n})\n\nblock('Delete all users', {\n  danger: true, // will ask for confirmation\n  query: (db, input) =\u003e (\n    db.delete(users)\n  ),\n})\n```\n\nBlock config signature:\n\n```ts\ninterface BlockConfig\u003cS extends Schema | undefined = undefined\u003e {\n  // Mark block as destructive (will ask for confirmation)\n  danger?: boolean\n  // Zod schema for validating input\n  schema?: S\n  // Async function to return or mutate data\n  query?: (db: ProvidedDatabase, input: InferBlockFnInput\u003cS\u003e) =\u003e Promise\u003cany\u003e | any\n  // Async function for operations with side-effects\n  run?: (db: ProvidedDatabase, input: InferBlockFnInput\u003cS\u003e) =\u003e Promise\u003cany\u003e | any\n}\n```\n\n### Running Castor\n\nJust run it:\n\n```bash\ncastor\n\n# or with config\ncastor --config path/to/config.ts\n\n# or with a script (recommended)\npnpm db:client\n```\n\nYou'll see a menu to select and run blocks.\n\nSample output:\n\n```bash\n🦫  Castor DB Client\n\nConfig file not found at `castor.config.ts`. Using default config.\n6 blocks loaded. 2 namespaces loaded. 🔗\n\n✔ Select a namespace to open · user\nOpening namespace: user (5 blocks)\n\n✔ Select a block to run · List all users\nPage 1 of 30\nShowing rows 1-5 of 150\n┌─────────┬───────────────┬──────────┐\n│ (index) │ id            │ name     │\n├─────────┼───────────────┼──────────┤\n│ 0       │ 'dj2bh08yf2s' │ 'User 1' │\n│ 1       │ 'xizda46r5m8' │ 'User 2' │\n│ 2       │ 'il6qpw38j6'  │ 'User 3' │\n│ 3       │ 'l3uoalp72o8' │ 'User 4' │\n│ 4       │ 'eprfnwls63g' │ 'User 5' │\n└─────────┴───────────────┴──────────┘\n? Navigation: …\n▸ [\u003e]\n  [30]\n  Go to specific page\n  Query menu\n```\n\n### How It Works\n\nCastor scans your codebase for \"blocks\" — reusable JS/TS query definitions — and lets you execute them through a guided CLI interface.\n\nEach block can:\n\n* Define a `schema` (input form, type-validated)\n* Contain a `query()` and/or `run()` function using `drizzle-orm`\n* Be marked as `danger` (destructive and will ask for confirmation)\n\nIt connects to a database (D1 or custom), prompts the user for any necessary input, runs the logic and prints the result.\n\n## FAQ\n\n**Q: What databases are supported?**\nA: Currently Cloudflare D1 (via `wrangler`). You can plug in any db via a `dbProvider()`.\n\n**Q: Can I organize blocks in folders?**\nA: Yep. Just drop them anywhere inside `rootDir`, unless excluded via glob.\n\n**Q: What happens when I run a block?**\nA: You're prompted for inputs (based on its schema), then Castor runs the logic and prints a table.\n\n## Contribute\n\nGot feedback, ideas, or just want to help shape Castor? Open an issue or send a PR. Contributions are welcome at any stage.\n\nCheck out the [contributing guide](./CONTRIBUTING.md) for details.\n\n## Roadmap\n\nIf you're curious about Castor's upcoming features or brainstorming sessions, take a look at the comments in the source code.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F9aia%2Fcastor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F9aia%2Fcastor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F9aia%2Fcastor/lists"}