{"id":49813354,"url":"https://github.com/dortort/keystone","last_synced_at":"2026-05-13T02:30:46.931Z","repository":{"id":336674984,"uuid":"1150679744","full_name":"dortort/keystone","owner":"dortort","description":"Open-source Electron app for AI-assisted software architecture, helping generate and refine PRDs, TDDs, and ADRs","archived":false,"fork":false,"pushed_at":"2026-02-06T01:11:38.000Z","size":215,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-06T01:54:05.411Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/dortort.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-05T15:07:43.000Z","updated_at":"2026-02-05T19:07:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dortort/keystone","commit_stats":null,"previous_names":["dortort/keystone"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/dortort/keystone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dortort%2Fkeystone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dortort%2Fkeystone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dortort%2Fkeystone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dortort%2Fkeystone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dortort","download_url":"https://codeload.github.com/dortort/keystone/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dortort%2Fkeystone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32965212,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T23:30:32.555Z","status":"online","status_checked_at":"2026-05-13T02:00:07.132Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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-05-13T02:30:44.373Z","updated_at":"2026-05-13T02:30:46.921Z","avatar_url":"https://github.com/dortort.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keystone\n\n[![CI](https://github.com/dortort/keystone/actions/workflows/ci.yml/badge.svg)](https://github.com/dortort/keystone/actions/workflows/ci.yml)\n[![Build](https://github.com/dortort/keystone/actions/workflows/build.yml/badge.svg)](https://github.com/dortort/keystone/actions/workflows/build.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n[![Electron](https://img.shields.io/badge/Electron-34-47848F?logo=electron\u0026logoColor=white)](https://www.electronjs.org/)\n[![React](https://img.shields.io/badge/React-19-61DAFB?logo=react\u0026logoColor=white)](https://react.dev/)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178C6?logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-3.4-06B6D4?logo=tailwindcss\u0026logoColor=white)](https://tailwindcss.com/)\n[![Vite](https://img.shields.io/badge/Vite-7-646CFF?logo=vite\u0026logoColor=white)](https://vite.dev/)\n[![Vitest](https://img.shields.io/badge/Vitest-3-6E9F18?logo=vitest\u0026logoColor=white)](https://vitest.dev/)\n\n\u003e AI-assisted software architecture documentation\n\nKeystone is an open-source Electron desktop application that streamlines the creation and maintenance of software architecture documentation through conversational AI. Generate, refine, and maintain **PRDs** (Product Requirements Documents), **TDDs** (Technical Design Documents), and **ADRs** (Architecture Decision Records) with AI assistance.\n\n## Features\n\n- **Multi-threaded AI Conversations**: Maintain parallel conversation threads with full context persistence\n- **Side-by-Side Workspace**: Conversations and documents live together in a unified interface\n- **Highlight-to-Interact**: Select any document section to inquire or refine\n- **ADR Generation**: Automatic architecture decision records when pivoting decisions\n- **Provider Agnostic**: Works with OpenAI, Google Gemini, and Anthropic Claude\n\n## Documentation\n\n- [Product Requirements Document](docs/PRD.md)\n- [Technical Design Document](docs/TDD.md)\n\n---\n\n## Getting Started\n\n### Prerequisites\n\n- **Node.js**\n- **pnpm**\n- **Git**\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/dortort/keystone.git\ncd keystone\n\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n```\n\n### Running the App\n\n```bash\n# Development mode with hot reload\npnpm dev\n\n# Build for production\npnpm build\n\n# Run production build\npnpm start\n```\n\n---\n\n## Development Environment\n\n### Recommended Setup\n\n| Tool | Purpose |\n|------|---------|\n| **VS Code** / **Cursor** | Primary IDE |\n| **ESLint** | Code linting |\n| **Prettier** | Code formatting |\n| **TypeScript** | Type checking |\n\n### IDE Extensions\n\n- ESLint\n- Prettier - Code formatter\n- Tailwind CSS IntelliSense\n- GitLens\n\n### Environment Variables\n\nCreate a `.env.local` file in the project root:\n\n```bash\n# Optional: API key fallbacks (subscription auth preferred)\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\nGOOGLE_API_KEY=...\n```\n\n---\n\n## Trunk-Based Development\n\nWe follow **trunk-based development** with short-lived feature branches.\n\n### Branch Naming Convention\n\n| Type | Pattern | Example |\n|------|---------|---------|\n| Feature | `feat/\u003cdescription\u003e` | `feat/add-adr-generation` |\n| Bug fix | `fix/\u003cdescription\u003e` | `fix/thread-context-loss` |\n| Chore | `chore/\u003cdescription\u003e` | `chore/update-deps` |\n| Docs | `docs/\u003cdescription\u003e` | `docs/api-reference` |\n| Refactor | `refactor/\u003cdescription\u003e` | `refactor/orchestrator` |\n| CI/CD | `ci/\u003cdescription\u003e` | `ci/add-e2e-tests` |\n\n### Workflow\n\n```\nmain\n  │\n  ├── feat/add-adr-generation (short-lived, \u003c 2 days)\n  │     └── PR → main\n  │\n  └── fix/thread-context-loss (short-lived)\n        └── PR → main\n```\n\n1. **Create branch** from `main`: `git checkout -b feat/my-feature`\n2. **Commit frequently** with conventional commits\n3. **Open PR early** (draft if WIP)\n4. **Keep branches short-lived** (\u003c 2 days ideally)\n5. **Rebase before merge** to maintain linear history\n\n### Commit Messages\n\nWe use [Conventional Commits](https://www.conventionalcommits.org/):\n\n```\n\u003ctype\u003e(\u003cscope\u003e): \u003cdescription\u003e\n\n[optional body]\n\n[optional footer(s)]\n```\n\n**Types:**\n- `feat`: New feature\n- `fix`: Bug fix\n- `docs`: Documentation only\n- `style`: Formatting (no code change)\n- `refactor`: Code change that neither fixes a bug nor adds a feature\n- `test`: Adding tests\n- `chore`: Build process or auxiliary tool changes\n\n**Examples:**\n```bash\ngit commit -m \"feat(orchestrator): add decision pivot detection\"\ngit commit -m \"fix(ui): resolve thread list scroll issue\"\ngit commit -m \"docs: update API reference\"\n```\n\n---\n\n## GitHub Actions CI/CD\n\n### Workflows\n\n| Workflow | Trigger | Purpose |\n|----------|---------|---------|\n| **CI** | Push, PR to `main` | Lint, type-check, test |\n| **Build** | Push to `main` | Build \u0026 package for all platforms |\n| **Release** | Tag `v*` | Create GitHub release with artifacts |\n\n### CI Pipeline\n\n```yaml\n# Runs on every push and pull request\n- Checkout code\n- Setup Node.js + pnpm\n- Install dependencies\n- Run linting (ESLint)\n- Run type checking (tsc)\n- Run unit tests (Vitest)\n- Run integration tests\n```\n\n### Required Checks\n\nAll PRs to `main` must pass:\n- ✅ Linting (`pnpm lint`)\n- ✅ Type checking (`pnpm typecheck`)\n- ✅ Unit tests (`pnpm test`)\n- ✅ Build succeeds (`pnpm build`)\n\n### Branch Protection\n\n`main` branch is protected with:\n- Require PR reviews (1 minimum)\n- Require status checks to pass\n- Require linear history (rebase merging)\n- No force pushes\n\n---\n\n## Coding Conventions\n\n### TypeScript\n\n- **Strict mode enabled** — No `any` types without justification\n- **Prefer interfaces** over type aliases for object shapes\n- **Use `readonly`** for immutable properties\n- **Explicit return types** for exported functions\n\n```typescript\n// ✅ Good\ninterface ThreadConfig {\n  readonly id: string;\n  maxMessages: number;\n}\n\nexport function createThread(config: ThreadConfig): Thread {\n  // ...\n}\n\n// ❌ Avoid\nexport const createThread = (config: any) =\u003e {\n  // ...\n}\n```\n\n### React Components\n\n- **Functional components** with hooks\n- **Named exports** for components\n- **Props interface** named `\u003cComponent\u003eProps`\n- **Colocate** styles, tests, and types\n\n```typescript\n// ✅ Good\ninterface ThreadListProps {\n  threads: Thread[];\n  onSelect: (id: string) =\u003e void;\n}\n\nexport function ThreadList({ threads, onSelect }: ThreadListProps) {\n  return (\n    // ...\n  );\n}\n```\n\n### File Structure\n\n```\nsrc/\n├── main/                 # Electron main process\n│   ├── ipc/              # IPC handlers\n│   ├── services/         # Business logic\n│   └── index.ts\n├── renderer/             # React frontend\n│   ├── components/       # Reusable UI components\n│   ├── features/         # Feature-based modules\n│   │   ├── conversation/\n│   │   └── document/\n│   ├── hooks/            # Custom React hooks\n│   ├── stores/           # Zustand stores\n│   └── App.tsx\n├── shared/               # Shared types and utilities\n│   ├── types/\n│   └── utils/\n└── agents/               # AI agent implementations\n    ├── orchestrator/\n    └── specialists/\n```\n\n### Naming Conventions\n\n| Element | Convention | Example |\n|---------|------------|---------|\n| Files (components) | PascalCase | `ThreadList.tsx` |\n| Files (utilities) | camelCase | `formatDate.ts` |\n| Files (types) | PascalCase | `Thread.ts` |\n| Interfaces | PascalCase | `ThreadConfig` |\n| Functions | camelCase | `createThread` |\n| Constants | SCREAMING_SNAKE | `MAX_THREADS` |\n| CSS classes | kebab-case | `thread-list-item` |\n\n### Import Order\n\n```typescript\n// 1. Built-in Node modules\nimport path from 'path';\n\n// 2. External packages\nimport React from 'react';\nimport { useStore } from 'zustand';\n\n// 3. Internal aliases (@/)\nimport { Thread } from '@/shared/types';\nimport { formatDate } from '@/shared/utils';\n\n// 4. Relative imports\nimport { ThreadItem } from './ThreadItem';\nimport styles from './ThreadList.module.css';\n```\n\n---\n\n## Testing\n\n### Test Stack\n\n| Type | Tool | Location |\n|------|------|----------|\n| Unit | Vitest | `*.test.ts` colocated |\n| Component | Vitest + Testing Library | `*.test.tsx` colocated |\n| E2E | Playwright | `e2e/` directory |\n\n### Running Tests\n\n```bash\n# Run all unit tests\npnpm test\n\n# Run tests in watch mode\npnpm test:watch\n\n# Run tests with coverage\npnpm test:coverage\n\n# Run E2E tests\npnpm test:e2e\n```\n\n### Test Naming\n\n```typescript\ndescribe('ThreadList', () =\u003e {\n  it('should render all threads', () =\u003e {\n    // ...\n  });\n\n  it('should call onSelect when thread is clicked', () =\u003e {\n    // ...\n  });\n});\n```\n\n---\n\n## Scripts Reference\n\n```bash\npnpm dev          # Start development server\npnpm build        # Build for production\npnpm start        # Run production build\npnpm lint         # Run ESLint\npnpm lint:fix     # Fix ESLint issues\npnpm typecheck    # Run TypeScript type check\npnpm test         # Run unit tests\npnpm test:watch   # Run tests in watch mode\npnpm test:e2e     # Run E2E tests\npnpm format       # Format code with Prettier\n```\n\n---\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`feat/amazing-feature`)\n3. Commit your changes using conventional commits\n4. Push to your fork\n5. Open a Pull Request\n\nPlease ensure your PR:\n- Passes all CI checks\n- Includes tests for new functionality\n- Updates documentation as needed\n- Follows the coding conventions above\n\n---\n\n## License\n\nThis project is open source. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdortort%2Fkeystone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdortort%2Fkeystone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdortort%2Fkeystone/lists"}