synapse-cc: Unified compiler toolchain for Plexus backends

[ development, library, mit, program ] [ Propose Tags ] [ Report a vulnerability ]

synapse-cc orchestrates the complete pipeline from backend schema discovery to compiled, ready-to-use client libraries.


[Skip to Readme]

Flags

Manual Flags

NameDescriptionDefault
live-tests

Build synapse-cc-test, which needs a substrate backend registered at 127.0.0.1:4444. Opt-in, so a default `cabal test` needs nothing running. Enable with: cabal test -f live-tests

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.2.0, 0.3.2, 0.3.3, 0.4.0
Change log CHANGELOG.md
Dependencies aeson (>=2.0), aeson-pretty (>=0.8), ansi-terminal (>=0.11), async (>=2.2), base (>=4.14 && <5), base16-bytestring (>=1.0), bytestring (>=0.11), containers (>=0.6), cryptohash-sha256 (>=0.11), directory (>=1.3), filepath (>=1.4), fsnotify (>=0.4), katip (>=0.8 && <0.9), mtl (>=2.3), optparse-applicative (>=0.18), plexus-protocol (>=0.6 && <0.7), plexus-synapse (>=4.0 && <5), process (>=1.6), stm (>=2.5), synapse-cc, text (>=1.2), time (>=1.9), transformers (>=0.6), unordered-containers (>=0.2) [details]
License MIT
Author Hypermemetic
Maintainer dev@hypermemetic.com
Uploaded by hypermemetic at 2026-11-04T23:33:14Z
Category Development
Distributions
Executables synapse-cc
Downloads 118 total (18 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2026-11-05 [all 1 reports]

Readme for synapse-cc-0.4.0

[back to package description]

synapse-cc

Unified compiler toolchain for Plexus backends

synapse-cc (synapse compiler collection) orchestrates the complete pipeline from backend schema discovery to compiled, ready-to-use client libraries.

Features

  • 🔧 Unified Interface: Single command to generate clients from any backend
  • 🔍 Smart Tool Discovery: Finds local development builds or installed versions
  • ⚡ Fast: Incremental caching skips regeneration when schemas haven't changed (IR cache at ~/.cache/plexus-codegen/synapse/ir/, per-file code cache via service-codegen)
  • 🎯 Multi-Language: TypeScript and Rust today (rust requires a service-codegen built with --features rust); python parses but has no generator yet
  • 🛠️ Complete Pipeline: schema → IR → generated code → installed deps → compiled artifact → smoke tests
  • 🔐 Credential lifecycle: Per-backend defaults store shared with synapse — set, inspect, and rotate JWTs / cookies / headers via synapse-cc _self <backend> …. Values held as reference URIs (literal:, env://, file://, keychain://) so secrets live in the OS keychain or env vars, not plaintext. JWT decoding flags expired tokens at a glance.

Installation

From Source

cd synapse-cc
cabal build
cabal install

Dependencies

synapse-cc requires these tools to be available:

  • synapse - Schema discovery and IR generation
  • service-codegen ≥ 0.5.0 - Code generation from IR. Earlier releases write a parameter the server injects (pdSource: auth, header, derived, …) into the generated methods as an optional unknown argument; synapse-cc says so when it finds one (SYNAPSE-CC-2)

The tool will automatically find them if they're:

  • In your $PATH
  • In local development directories (../synapse, ../service-codegen)
  • In ~/.plexus/bin/

The generator is service-codegen (0.5.1 on; NAMING-10 — a Plexus backend is a service). synapse-cc 0.3.6 looks for it under that name first — on $PATH, then ../service-codegen/target/…, ~/.plexus/bin, ~/.cargo/bin — and only then under its old name, saying the old name is deprecated. Its path is --service-codegen PATH (the old flag still works for one release, hidden, with a note). synapse.lock is written with serviceCodegen, the generator's JSON is read as serviceCodegenVersion, a code cache's toolchain as tvServiceCodegen; each old key is still read. NAMING-18 removes the old names; scripts/naming-gate.sh (the naming test suite) fails on a new one. synapse-cc 0.3.6 builds against plexus-synapse 3.14.3 up to 3.17.

Usage

The CLI is subcommand-shaped:

synapse-cc init [BACKEND]                  # scaffold synapse.config.json
synapse-cc build                           # build every target in synapse.config.json
synapse-cc build TARGET BACKEND [OPTIONS]  # one-off build, no config file
synapse-cc watch BACKEND [PLUGIN...]       # rebuild on schema changes
synapse-cc wait [BACKEND]                  # block until backend(s) reachable
synapse-cc _self BACKEND VERB ...          # credentials store (shared with synapse)

Quickstart (config-driven)

A service scaffolded by axon new ships a synapse.config.json pre-pointed at itself — synapse-cc build works unedited from the service directory (server must be running). Real run:

$ synapse-cc build
==> Discovering tools...
[+] Found all required tools
[i] Building "client" → src/lib/plexus

==> Reading schema...
[+] Schema ready (2 plugins)

==> Generating code...
[+] Code generated (11 files)

==> Installing dependencies...
[+] Dependencies installed

==> Building...
[+] Build passed

==> Running tests...
[+] Tests passed
[+] client → src/lib/plexus/

Without a config file, synapse-cc init <backend> scaffolds one; with the backend argument omitted it is inferred — from a co-located Plexus service crate, then from the local registry — and the inference is announced. There is no silent default backend:

$ synapse-cc init
[!] missing BACKEND argument — no co-located Plexus service crate found and
    no backend discoverable on the registry at 127.0.0.1:4444.
    Run: synapse-cc init <backend>

Quickstart (one-off, no config)

synapse-cc build typescript substrate          # TS client → ./generated/
synapse-cc build rust substrate -o ./client    # Rust client, ends in cargo build

The backend is resolved by name via the registry (endpoint from PLEXUS_REGISTRY_URL, default ws://127.0.0.1:4444; -H/-P set the fallback). A real rust run:

$ synapse-cc build rust zechodev -o ./rust-client
==> Discovering tools...
[+] Found all required tools

==> Resolving zechodev via registry at ws://127.0.0.1:4444...

==> Reading schema...
[+] Schema ready (2 plugins)

==> Generating code...
[+] Code generated (5 files)

==> Building...
[+] Build passed

==> Running tests...
[+] Tests passed

[+] Client → ./rust-client/

-t rust ends in a real cargo build of the generated crate (Z2H-7) — the artifact compiles or the command fails.

Options (build / watch)

  -o, --output DIR        Output directory (default: ./generated)
  --transport ws|browser  ws (Node.js, default) or browser (native WebSocket,
                          for Tauri/WebView)
  --no-install            Skip dependency installation
  --no-build              Skip compilation step
  --no-tests              Skip running smoke tests
  --cache-dir DIR         Cache directory (default: ~/.cache/plexus-codegen)
  --force                 Force regeneration (ignore cache)
  --debug                 Enable debug logging
  --synapse PATH          synapse binary path (overrides discovery)
  --service-codegen PATH      service-codegen binary path (overrides discovery)
  -t, --token JWT         JWT auth token (see Credentials below)
  --token-file PATH       Read JWT from file
  -H, --host HOST         Registry/discovery host (default: 127.0.0.1)
  -P, --port PORT         Registry/discovery port (default: 4444)

Rust target prerequisite

build rust requires a service-codegen binary compiled with the rust feature (cargo build --release --features all in the service-codegen repo). A typescript-only binary fails with:

[!] Error: service-codegen failed (exit code 1)
Error: Rust codegen not enabled. Rebuild with --features rust

Point --service-codegen at a rust-enabled build if the discovered one is not.

Credentials & Headers

synapse-cc shares a single defaults store with synapse at ~/.plexus/<backend>/defaults.json. Any JWT, cookie, or header you set via either CLI is immediately visible to the other. The file holds credential-reference URIs (literal:, env://, file://, keychain://), resolved at request time.

# Inspect what's stored + decode any JWTs + flag expired tokens
synapse-cc _self <backend> show

# Store a JWT (auto-wrapped as literal:)
synapse-cc _self <backend> set cookie access_token "eyJ..."

# Store a reference to an env var (preferred in CI)
synapse-cc _self <backend> set cookie access_token "env://MY_JWT"

# Import a JWT file
synapse-cc _self <backend> import-token ~/Downloads/jwt.txt

# Clear all defaults for a backend
synapse-cc _self <backend> clear --yes

The _self subcommand tree is identical to synapse _self <backend> … — they share the same library implementation. See synapse's README for the full verb list, URI scheme reference, and legacy ~/.plexus/tokens/<backend> migration behavior.

Per-invocation overrides: --token <jwt>, SYNAPSE_TOKEN env, --token-file <path>, --cookie KEY=VALUE, --header KEY=VALUE — all flow through the same priority chain as synapse, with CLI values winning over stored defaults per key.

Architecture

synapse-cc (Haskell)
    ↓
    ├─→ synapse (Haskell) → IR (JSON)
    ↓
    ├─→ service-codegen (Rust) → Generated Code
    ↓
    └─→ Language Tools (npm, tsc, etc.) → Compiled Artifact

Development

Project Structure

synapse-cc/
├── synapse-cc.cabal         # Cabal project file
├── app/
│   └── Main.hs              # Entry point, subcommand dispatch
└── src/
    └── SynapseCC/
        ├── Types.hs           # Core types, Options, synapse.config.json types
        ├── CLI.hs             # Subcommand + option parsing
        ├── Config.hs          # synapse.config.json load/init
        ├── Detect.hs          # Project detection for `init` inference
        ├── Discover.hs        # Tool discovery (synapse, service-codegen)
        ├── RegistryResolve.hs # Backend-name resolution via the registry
        ├── Pipeline.hs        # Pipeline orchestration
        ├── Process.hs         # Subprocess helpers
        ├── Cache.hs           # Incremental IR caching
        ├── Merge.hs           # Three-way merge bookkeeping
        ├── Dependency.hs      # Plugin dependency resolution
        ├── Language.hs        # Per-language install/build/test steps
        ├── Auth.hs            # Token priority chain (wraps Synapse.Self)
        ├── Watch.hs           # watch subcommand
        ├── Wait.hs            # wait subcommand
        └── Logging.hs         # Pretty output

Building

cabal build

Running from source

cabal run synapse-cc -- build typescript substrate --debug

Testing

# Scaffold and start a throwaway backend (any free port)
axon new mysvc --port 4452 && cd mysvc && cargo run &

# Generate, compile, and smoke-test a client against it — the scaffold's
# synapse.config.json is already pointed at ws://127.0.0.1:4452
synapse-cc build

Status

Shipped: tool discovery, pipeline orchestration, config-driven multi-target builds (synapse.config.json), incremental IR + code caching with three-way merge, dependency installation + compile + smoke-test steps (bun/npm for TypeScript, cargo for Rust), watch mode, wait, registry-based backend resolution (PLEXUS_REGISTRY_URL), shared credentials store (_self).

Not shipped: a python generator (the target parses; service-codegen has no emitter), remote/distributed caching.

Contributing

See PLAN.md for detailed implementation plan and design decisions.

License

MIT