{"id":34694095,"url":"https://github.com/plures/praxis","last_synced_at":"2026-04-06T23:01:28.005Z","repository":{"id":324788322,"uuid":"1097304493","full_name":"plures/praxis","owner":"plures","description":"The Full Plures Application Framework","archived":false,"fork":false,"pushed_at":"2026-04-02T22:28:00.000Z","size":2026,"stargazers_count":0,"open_issues_count":13,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T01:44:53.723Z","etag":null,"topics":["database","deno","documentation","local-first","logic-programming","state","svelte","tarui"],"latest_commit_sha":null,"homepage":"https://plures.io","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/plures.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["plures"]}},"created_at":"2025-11-15T23:05:33.000Z","updated_at":"2026-04-02T22:28:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/plures/praxis","commit_stats":null,"previous_names":["plures/praxis"],"tags_count":111,"template":false,"template_full_name":null,"purl":"pkg:github/plures/praxis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plures%2Fpraxis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plures%2Fpraxis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plures%2Fpraxis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plures%2Fpraxis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plures","download_url":"https://codeload.github.com/plures/praxis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plures%2Fpraxis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31492751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T17:22:55.647Z","status":"ssl_error","status_checked_at":"2026-04-06T17:22:54.741Z","response_time":112,"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":["database","deno","documentation","local-first","logic-programming","state","svelte","tarui"],"created_at":"2025-12-24T22:26:05.085Z","updated_at":"2026-04-06T23:01:27.996Z","avatar_url":"https://github.com/plures.png","language":"TypeScript","funding_links":["https://github.com/sponsors/plures"],"categories":[],"sub_categories":[],"readme":"# Praxis\n\n[![CI](https://github.com/plures/praxis/actions/workflows/ci.yml/badge.svg)](https://github.com/plures/praxis/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/%40plures%2Fpraxis.svg)](https://www.npmjs.com/package/@plures/praxis)\n[![JSR](https://jsr.io/badges/@plures/praxis)](https://jsr.io/@plures/praxis)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n**The full-stack declarative application framework — typed logic, reactive state, local-first data, and visual tooling for Svelte, Node, and the browser.**\n\nPraxis 2.0 gives you a single `createApp()` call that wires reactive state, constraint validation, rule evaluation, and an immutable timeline — zero boilerplate. When you need deeper control, drop down to the classic engine with registries, typed events/facts, and undo/redo history.\n\n## Install\n\nNode 18+ recommended.\n\n```bash\nnpm install @plures/praxis   # or: pnpm add @plures/praxis\n```\n\n## API Reference\n\nSee [`docs/API.md`](./docs/API.md) for the exported public API surface.\n\n## Quick Start — Unified App (v2.0)\n\nThe fastest way to build with Praxis. Define paths (state), rules, and constraints — Praxis handles the rest.\n\n```ts\nimport {\n  createApp,\n  definePath,\n  defineRule,\n  defineConstraint,\n  RuleResult,\n  fact,\n} from '@plures/praxis/unified';\n\n// 1. Declare your state shape\nconst Count = definePath\u003cnumber\u003e('count', 0);\nconst Max   = definePath\u003cnumber\u003e('max', 10);\n\n// 2. Add constraints\nconst notNegative = defineConstraint({\n  id: 'count.not-negative',\n  description: 'Count must never go below zero',\n  watch: ['count'],\n  validate: (values) =\u003e values['count'] \u003e= 0 || 'Count cannot be negative',\n});\n\n// 3. Add rules\nconst capAtMax = defineRule({\n  id: 'count.cap',\n  watch: ['count', 'max'],\n  evaluate: (values) =\u003e {\n    if (values['count'] \u003e values['max']) {\n      return RuleResult.emit([fact('count.capped', { at: values['max'] })]);\n    }\n    return RuleResult.noop();\n  },\n});\n\n// 4. Create the app\nconst app = createApp({\n  name: 'counter',\n  schema: [Count, Max],\n  rules: [capAtMax],\n  constraints: [notNegative],\n});\n\n// 5. Query \u0026 mutate\nconst count = app.query\u003cnumber\u003e('count');\nconsole.log(count.current); // 0\n\napp.mutate('count', 5);\nconsole.log(count.current); // 5\n\nconst result = app.mutate('count', -1);\nconsole.log(result.accepted); // false — constraint rejected\n```\n\n## Classic Engine (full control)\n\nFor complex scenarios that need typed events, facts, actors, and undo/redo:\n\n```ts\nimport {\n  createPraxisEngine,\n  PraxisRegistry,\n  defineFact,\n  defineEvent,\n  defineRule,\n} from '@plures/praxis';\n\nconst UserLoggedIn = defineFact\u003c'UserLoggedIn', { userId: string }\u003e('UserLoggedIn');\nconst Login = defineEvent\u003c'LOGIN', { username: string }\u003e('LOGIN');\n\nconst loginRule = defineRule\u003c{ currentUser: string | null }\u003e({\n  id: 'auth.login',\n  description: 'Authenticate and emit fact',\n  impl: (state, events) =\u003e {\n    const evt = events.find(Login.is);\n    if (!evt) return [];\n    state.context.currentUser = evt.payload.username;\n    return [UserLoggedIn.create({ userId: evt.payload.username })];\n  },\n});\n\nconst registry = new PraxisRegistry();\nregistry.registerRule(loginRule);\n\nconst engine = createPraxisEngine({ initialContext: { currentUser: null }, registry });\nengine.step([Login.create({ username: 'alex' })]);\nconsole.log(engine.getContext()); // { currentUser: 'alex' }\n```\n\n## Svelte 5 Integration\n\n### Runes API\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n  import { usePraxisEngine } from '@plures/praxis/svelte';\n  import { createMyEngine, Login } from './my-engine';\n\n  const engine = createMyEngine();\n  const { context, dispatch, undo, redo, canUndo, canRedo } = usePraxisEngine(engine, {\n    enableHistory: true,\n    maxHistorySize: 50,\n  });\n\u003c/script\u003e\n\n\u003cp\u003eUser: {context.currentUser || 'Guest'}\u003c/p\u003e\n\u003cbutton onclick={() =\u003e dispatch([Login.create({ username: 'alice' })])}\u003eLogin\u003c/button\u003e\n\u003cbutton onclick={undo} disabled={!canUndo}\u003e⟲ Undo\u003c/button\u003e\n\u003cbutton onclick={redo} disabled={!canRedo}\u003e⟳ Redo\u003c/button\u003e\n```\n\n### Store API\n\n```ts\nimport { createPraxisStore, createDerivedStore } from '@plures/praxis/svelte';\n\nconst stateStore = createPraxisStore(engine);\nconst userStore  = createDerivedStore(engine, (ctx) =\u003e ctx.currentUser);\n```\n\nSee [Svelte Integration Guide](./docs/guides/svelte-integration.md) for the full API including reactive engine, history patterns, and keyboard shortcuts.\n\n## Decision Ledger (Behavior Contracts)\n\nAttach explicit contracts to every rule and constraint — with Given/When/Then examples, invariants, and assumption tracking.\n\n```ts\nimport { defineContract, defineRule } from '@plures/praxis';\n\nconst loginContract = defineContract({\n  ruleId: 'auth.login',\n  behavior: 'Process login events and create user session facts',\n  examples: [\n    { given: 'Valid credentials', when: 'LOGIN event', then: 'UserSessionCreated fact emitted' }\n  ],\n  invariants: ['Session must have unique ID'],\n});\n\nconst loginRule = defineRule({\n  id: 'auth.login',\n  description: 'Process login events',\n  impl: (state, events) =\u003e { /* ... */ },\n  contract: loginContract,\n});\n```\n\n```bash\nnpm run scan:rules           # Index all rules/constraints\nnpm run validate:contracts   # Validate all contracts\nnpx praxis validate --strict # CI/CD enforcement\n```\n\nSee [Decision Ledger Guide](./docs/decision-ledger/DOGFOODING.md) for the full dogfooding workflow.\n\n## PluresDB — Local-First Persistence\n\n```ts\nimport { createInMemoryDB, createPluresDBAdapter } from '@plures/praxis';\n\nconst db = createInMemoryDB();\nconst adapter = createPluresDBAdapter({ db, registry });\nadapter.attachEngine(engine); // auto-persist facts \u0026 events\n```\n\nFor production, use the official [@plures/pluresdb](https://www.npmjs.com/package/@plures/pluresdb) package with P2P sync and CRDT conflict resolution:\n\n```ts\nimport { PluresNode } from '@plures/pluresdb';\nimport { createPluresDB } from '@plures/praxis';\n\nconst db = createPluresDB(new PluresNode({ config: { port: 34567, dataDir: './data' }, autoStart: true }));\n```\n\n## CLI\n\n```bash\nnpx praxis --help\nnpx praxis create app my-app\nnpx praxis generate --schema src/schemas/app.schema.ts\nnpx praxis canvas src/schemas/app.schema.ts\n```\n\n## Exports\n\n| Import path | Description |\n|---|---|\n| `@plures/praxis` | Core engine, DSL, protocol types, integrations |\n| `@plures/praxis/unified` | `createApp()` unified reactive layer |\n| `@plures/praxis/svelte` | Svelte 5 runes + store APIs |\n| `@plures/praxis/schema` | Schema types and loaders |\n| `@plures/praxis/component` | Svelte component generator |\n| `@plures/praxis/cloud` | Cloud relay sync |\n| `@plures/praxis/components` | Built-in Svelte components |\n| `@plures/praxis/mcp` | Model Context Protocol tools |\n| `@plures/praxis/expectations` | Behavior expectation DSL |\n| `@plures/praxis/factory` | Pre-built UI rule modules |\n| `@plures/praxis/project` | Project gates and lifecycle |\n| `praxis` (bin) | CLI entrypoint |\n\n## Core Protocol\n\nAll Praxis APIs build on a language-neutral, pure-function protocol:\n\n```ts\ninterface PraxisFact  { tag: string; payload: unknown }\ninterface PraxisEvent { tag: string; payload: unknown }\ninterface PraxisState { context: unknown; facts: PraxisFact[]; meta?: Record\u003cstring, unknown\u003e }\n\n// The conceptual core — pure, deterministic, no side effects\ntype PraxisStepFn = (state: PraxisState, events: PraxisEvent[], config: PraxisStepConfig) =\u003e PraxisStepResult;\n```\n\nImplemented in TypeScript (npm), C# (.NET 8+, NuGet: `Plures.Praxis`), and PowerShell. All share the same JSON wire format. See [CROSS_LANGUAGE_SYNC.md](./CROSS_LANGUAGE_SYNC.md) and [PROTOCOL_VERSIONING.md](./PROTOCOL_VERSIONING.md).\n\n## Examples\n\n| Example | Description | Location |\n|---|---|---|\n| Hero E-Commerce | Full-stack: auth, cart, discounts, loyalty, actors | `src/examples/hero-ecommerce/` |\n| Decision Ledger | Contracts, validation, SARIF output | `examples/decision-ledger/` |\n| Offline Chat | Local-first messaging with PluresDB | `examples/offline-chat/` |\n| Terminal Node | Command execution with YAML schemas | `examples/terminal-node/` |\n| Unified App | `createApp()` + rules + Mermaid docs | `examples/unified-app/` |\n| Cloud Sync | Real-time relay synchronization | `examples/cloud-sync/` |\n| Simple App | Minimal schema usage | `examples/simple-app/` |\n| Reactive Counter | Framework-agnostic reactive engine | `examples/reactive-counter/` |\n\nBrowse all examples in [`examples/`](./examples/) and [`src/examples/`](./src/examples/).\n\n## Documentation\n\n| Resource | Link |\n|---|---|\n| Getting Started | [GETTING_STARTED.md](./GETTING_STARTED.md) |\n| Framework Architecture | [FRAMEWORK.md](./FRAMEWORK.md) |\n| Core API Reference | [docs/core/praxis-core-api.md](./docs/core/praxis-core-api.md) |\n| Extending Praxis | [docs/core/extending-praxis-core.md](./docs/core/extending-praxis-core.md) |\n| Svelte Integration | [docs/guides/svelte-integration.md](./docs/guides/svelte-integration.md) |\n| CodeCanvas Guide | [docs/guides/canvas.md](./docs/guides/canvas.md) |\n| Decision Ledger | [docs/decision-ledger/DOGFOODING.md](./docs/decision-ledger/DOGFOODING.md) |\n| Tutorials | [docs/tutorials/](./docs/tutorials/) |\n| Migration from 1.x | [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md) |\n| Roadmap | [ROADMAP.md](./ROADMAP.md) |\n| 1.x Archive | [docs/archive/1.x/](./docs/archive/1.x/) |\n\n## Development\n\n```bash\nnpm install          # Install dependencies\nnpm run build        # Build (ESM + CJS via tsup)\nnpm test             # Run tests (Vitest)\nnpm run typecheck    # Type-check\n```\n\n## Contributing\n\nPRs and discussions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).\n\n- 🐛 [Report a bug](https://github.com/plures/praxis/issues/new?template=bug_report.yml)\n- 💡 [Request a feature](https://github.com/plures/praxis/issues/new?template=enhancement.yml)\n- 🔒 [Report a security issue](./SECURITY.md)\n\n## License\n\n[MIT](./LICENSE)\n\n---\n\n**Praxis** — practical, provable, portable application logic.\n\nBuilt with ❤️ by the [Plures](https://github.com/plures) team\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplures%2Fpraxis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplures%2Fpraxis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplures%2Fpraxis/lists"}