{"id":31900948,"url":"https://github.com/posit-dev/kallichore","last_synced_at":"2026-01-23T19:01:12.005Z","repository":{"id":317930613,"uuid":"819541973","full_name":"posit-dev/kallichore","owner":"posit-dev","description":"Cross-platform, high performance, headless Jupyter Kernel gateway and supervisor","archived":false,"fork":false,"pushed_at":"2026-01-21T18:34:45.000Z","size":1080,"stargazers_count":2,"open_issues_count":11,"forks_count":1,"subscribers_count":8,"default_branch":"main","last_synced_at":"2026-01-22T06:53:53.448Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/posit-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-24T18:03:59.000Z","updated_at":"2026-01-06T17:34:44.000Z","dependencies_parsed_at":"2026-01-07T16:08:54.782Z","dependency_job_id":null,"html_url":"https://github.com/posit-dev/kallichore","commit_stats":null,"previous_names":["posit-dev/kallichore"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/posit-dev/kallichore","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posit-dev%2Fkallichore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posit-dev%2Fkallichore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posit-dev%2Fkallichore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posit-dev%2Fkallichore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/posit-dev","download_url":"https://codeload.github.com/posit-dev/kallichore/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posit-dev%2Fkallichore/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28698343,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T17:25:48.045Z","status":"ssl_error","status_checked_at":"2026-01-23T17:25:47.153Z","response_time":59,"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":"2025-10-13T12:44:59.344Z","updated_at":"2026-01-23T19:01:11.986Z","avatar_url":"https://github.com/posit-dev.png","language":"Rust","readme":"# Kallichore \u003cimg src=\"doc/Kallichore.webp\" align=\"right\" height=160 /\u003e\n\nKallichore is an experimental, cross-platform, headless supervisor for Jupyter kernels. It [exposes an API](https://github.com/posit-dev/kallichore/blob/main/kallichore.json) that can be used to manage kernel sessions and provides a WebSocket-compatible interface for sending and receiving Jupyter messages to each kernel.\n\n```mermaid\ngraph LR\nfrontend -- http --\u003e kallichore\nkallichore -- websocket --\u003e frontend\nfrontend -- websocket --\u003e kallichore\nkallichore --\u003e ki1[kernel interface 1]\nkallichore --\u003e ki2[kernel interface 2]\nki1 -- zeromq --\u003e k1[kernel 1]\nki2 -- zeromq --\u003e k2[kernel 2]\n```\n\nKallichore's primary residence is in [the Positron IDE](https://github.com/posit-dev/positron), where it provides durable Jupyter kernel sessions, especially in [Posit Workbench](https://posit.co/products/enterprise/workbench/). It takes care of the low-level minutiae of Jupyter kernel management (ZeroMQ, process interop, lifecycle supervision, etc.), leaving Positron to handle the user interface and other aspects of the development environment.\n\nIt is a companion to Posit's [Amalthea and Ark](https://github.com/posit-dev/ark) projects. Like Amalthea, it is a Rust-based, Jupyter-adjacent project named after [one of Jupiter's moons](https://science.nasa.gov/jupiter/moons/kallichore/). Kallichore is also [one of the Muses](https://en.wikipedia.org/wiki/Callichore).\n\nHere's how Kallichore functions in the larger Positron ecosystem for e.g. an R session:\n\n```mermaid\ngraph TD\np[Positron] -- Positron API --\u003e r[R Language Pack]\nr -- Positron API --\u003e p\nr --\u003e kp[Kallichore Plugin]\nkp --\u003e r\nkp -- Kallichore API --\u003e k[Kallichore]\nk -- Kallichore API --\u003e kp\nk -- Jupyter over ZeroMQ --\u003e rk[R Kernel]\nrk -- Jupyter over ZeroMQ --\u003e k\nkp -- Jupyter over WebSocket --\u003e k\nrk -- LSP over TCP --\u003e r\n```\n\n## Running Kallichore\n\nTo run Kallichore, first get a copy of the server from the GitHub Releases page on this repository (or build your own; see below for instructions). This release contains a pre-built binary named `kcserver` for your platform.\n\nFor most use cases, it's recommended to run `kcserver` with the `--connection-file` argument to have Kallichore generate a connection file for your client. On a typical Unix-like system, you might use a temporary file for connection information and tell Kallichore to use domain sockets as the transport (TCP and named pipes are also supported; see [Connection Methods](#connection-methods) for details):\n\n```bash\n./kcserver --transport socket --connection-file /tmp/kc-connection-file.json\n```\n\nThe server will start up and listen for incoming connections on the specified transport and generate a bearer auth token (see below for [Security Considerations](#security-considerations)). Your client can read connection details from the connection file and connect to the server using the appropriate transport. The connection file looks like this:\n\n```json\n{\n  \"socket_path\": \"/tmp/path-to/socket/kc-5259.sock\",\n  \"transport\": \"socket\",\n  \"server_path\": \"/path/to/kcserver\",\n  \"server_pid\": 5259,\n  \"bearer_token\": \"4dea37b8a3b3e09f\",\n  \"log_path\": null\n}\n```\n\nSee Kallichore's help page for a full list of command-line options:\n\n```bash\n./kcserver --help\n```\n\n### Starting and Connecting to Kernels\n\nOnce the server is alive, you're ready to run kernels. Typically, you'll use the following API methods:\n\n- Create a new session by executing a `PUT` on `/sessions` with the session information. The new session ID is returned (let's say it's `session1234`)\n- Begin listening to kernel events and output from the session by getting a WebSocket URL or path from the `/sessions/session1234/channels` method and connecting to it in your client.\n- Ask the session to start by executing a `POST` on `/sessions/session1234/start`. During startup, state changes and output will be sent to the WebSocket connection.\n- Once the session is successfully started, use your WebSocket connection to send and receive messages to/from the kernel.\n\n### Kernel and Server Lifecycles\n\nBy default, the server will run indefinitely until it is manually stopped. You can stop it by sending a `SIGINT` signal to the process, or by invoking the `/shutdown` API. Either one will attempt to gracefully shut down all active kernels (sending each a Jupyter message requesting shutdown) and then exit the server itself.\n\nYou can also cause Kallichore to exit after a period of inactivity by setting the `--idle-shutdown-hours` parameter when starting the server. This option will keep the server running as long as any kernel is active; the shutdown timer starts running only when all kernels are idle and none are connected to a front end.\n\n## Security Considerations\n\n\u003e [!IMPORTANT]\n\u003e Kallichore's API accepts arbitrary paths to executable files, and will run them as subprocesses. Jupyter kernels can also be made to execute arbitrary commands, which can be used to execute malicious code. This presents a significant security risk if security measures are not in place to prevent unauthorized execution.\n\nThe following steps are recommended to ensure the security of your Kallichore instance:\n\n1. **Use a low-privilege user account**: Run Kallichore under a non-privileged user account, not as root. Because Jupyter kernels are basically code execution environments, presume that giving a user access to Kallichore's API is equivalent to giving them shell access.\n2. **Use IPC, not TCP**: If running Kallichore locally, use domain sockets (Unix/macOS) or named pipes (Windows) as the transport. These transports are more secure than TCP, as they can be locked down with file system permissions and do not expose the server to the network.\n3. **Secure the authentication token**: Kallichore uses a simple bearer token for authentication. If generating the token yourself, pass it as a file (so that it is not exposed in the process list) and delete it once the server has started. If allowing the server to generate the token, delete the connection file once it has been read.\n\n## Development\n\n### Compiling\n\nTo compile the Kallichore project, just run this in the root directory of the repository:\n\n```bash\ncargo build\n```\n\n### Running\n\nRun the server from the `target` directory. You may want to set `RUST_LOG` to `trace` to get detailed debugging output.\n\n```bash\nexport RUST_LOG=trace\n./target/debug/kcserver\n```\n\n## Repository Structure\n\n```\n .\n +-- kallichore.json -- OpenAPI description of the Kallichore API\n |\n +-- crates\n      |\n      +-- kallichore_api -- Code-generated Rust client/server\n      |    |\n      |    +-- examples/client -- Example client\n      |    |\n      |    +-- examples/server -- Example server\n      |\n      +-- kcshared -- Shared code for the server and client\n      |\n      +-- kcserver -- Main Kallichore server, using the kallichore_api crate\n      |\n      +-- kcclient -- Command-line client (for testing), using the kallichore_api crate\n```\n\n## API Changes\n\nTo make changes to the API, edit the `kallichore.json` file and then run the `scripts/regen-api.sh` script to regenerate the Rust client and server crates.\n\n```bash\n./scripts/regen-api.sh\n```\n\n\u003e [!NOTE]\n\u003e The regenerator script requires the [OpenAPI Generator](https://openapi-generator.tech/docs/installation).\n\n\u003e [!IMPORTANT]\n\u003e The code generator produces code with HTTPS support. We remove the TLS/HTTPS support from the generated code in order to avoid creating a binary that links to OpenSSL (which would introduce a lot of system compatibility issues).\n\n## Connection Methods\n\nKallichore supports multiple transport mechanisms for client connections. The server can be configured to use TCP, Unix domain sockets, or Windows named pipes.\n\n### TCP (Default)\n\nTCP is the default transport method that works across all platforms. In TCP mode, the supervisor listens on a local TCP port and accepts RPCs over HTTP. This is suitable for remote connections and works on all operating systems.\n\nConnections to individual kernels are made with WebSockets, which are established over the HTTP connection.\n\n#### Starting the server with TCP\n\n```bash\n# Use default port (random)\n./kcserver\n\n# Use specific port\n./kcserver --port 8080\n\n# Create a connection file with TCP\n./kcserver --connection-file connection.json --transport tcp\n```\n\n#### Example TCP connection file\n\nWhen using `--connection-file`, the server writes connection details to the specified file:\n\n```json\n{\n  \"port\": 54321,\n  \"base_path\": \"http://127.0.0.1:54321\",\n  \"transport\": \"tcp\",\n  \"server_path\": \"/path/to/kcserver\",\n  \"server_pid\": 12345,\n  \"bearer_token\": \"your-auth-token\",\n  \"log_path\": \"/path/to/logfile.log\"\n}\n```\n\n### Unix Domain Sockets (Unix/Linux/macOS)\n\nUnix domain sockets provide high-performance IPC for local connections on Unix-like systems. They offer better security than TCP, since they use filesystem permissions. However, they are not available on Windows and are not suitable for remote connections.\n\nWhen using domain sockets, the server listens on a specific socket file instead of a TCP port. When connecting to individual kernels, each kernel gets a dedicated Unix socket for communication.\n\n#### Starting the server with Unix sockets\n\n```bash\n# Use connection file with socket (default on Unix when using --connection-file)\n./kcserver --connection-file connection.json\n\n# Explicitly specify socket transport\n./kcserver --connection-file connection.json --transport socket\n\n# Use specific socket path\n./kcserver --unix-socket /tmp/kallichore.sock\n```\n\n#### Example Unix socket connection file\n\n```json\n{\n  \"socket_path\": \"/tmp/kallichore-12345.sock\",\n  \"transport\": \"socket\",\n  \"server_path\": \"/path/to/kcserver\",\n  \"server_pid\": 12345,\n  \"bearer_token\": \"your-auth-token\",\n  \"log_path\": \"/path/to/logfile.log\"\n}\n```\n\n### Named Pipes (Windows)\n\nNamed pipes are the Windows equivalent of Unix domain sockets, providing efficient local IPC on Windows systems. They are not available on Unix-like systems and are only used for local connections.\n\nWhen using named pipes, the server listens on a named pipe path instead of a TCP port or Unix socket. Each kernel session also gets its own named pipe for communication.\n\n#### Starting the server with named pipes\n\n```bash\n# Use connection file with named pipe (default on Windows when using --connection-file)\nkcserver.exe --connection-file connection.json\n\n# Explicitly specify named pipe transport\nkcserver.exe --connection-file connection.json --transport named-pipe\n```\n\n#### Example named pipe connection file\n\n```json\n{\n  \"named_pipe\": \"\\\\\\\\.\\\\pipe\\\\kallichore-12345\",\n  \"transport\": \"named-pipe\",\n  \"server_path\": \"C:\\\\path\\\\to\\\\kcserver.exe\",\n  \"server_pid\": 12345,\n  \"bearer_token\": \"your-auth-token\",\n  \"log_path\": \"C:\\\\path\\\\to\\\\logfile.log\"\n}\n```\n\n### Transport Selection Rules\n\nThe server automatically selects the appropriate transport based on:\n\n1. **Explicit `--transport` flag**: Overrides all other settings\n2. **Connection file mode**: Defaults to `socket` on Unix, `named-pipe` on Windows, `tcp` elsewhere\n3. **Direct mode**: Uses `tcp` when no connection file is specified\n\n### Security Considerations\n\n- **TCP**: Binds to `127.0.0.1` (localhost only) by default for security\n- **Unix Sockets**: Use filesystem permissions for access control\n- **Named Pipes**: Use Windows security descriptors for access control\n- **Authentication**: All transports support bearer token authentication when enabled\n\n\n## Builds and Versions\n\nKallichore is versioned similar to ARK. No release builds are produced by default. When you want to release a new version of Kallichore (for integrating into Positron, etc.), bump the version of the `kcserver` crate. This will trigger a release build.\n\n## Adjacent Projects/Links\n\n[Jupyter Kernel Gateway](https://jupyter-kernel-gateway.readthedocs.io/en/latest/): a headless Jupyter server that uses WebSockets to deliver Jupyter messages.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposit-dev%2Fkallichore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fposit-dev%2Fkallichore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposit-dev%2Fkallichore/lists"}