Skip to content

Pack catalog ​

Every pack ships inside the CLI, so there is one install and nothing else to add:

bash
npm install --save-dev @suss/cli

Sixty-two packs read code today, across fifty-one frameworks, eight HTTP and GraphQL clients, and the Node runtime. Ten contract readers turn a declared artifact into summaries in the same format. @suss/contract-intent reads the intent documents your team writes, separately from all of those.

Most of that is TypeScript and JavaScript. Four of the packs read another language: flask-restx and FastAPI read Python through @suss/adapter-python, and graphql-ruby and rails read Ruby through @suss/adapter-ruby. suss extract runs those two adapters as well, and the Python and Ruby guide shows how.

The quickest way to find your packs is to let suss look:

bash
suss init

It reads your dependencies, tells you which packs match, and offers to write them into suss.json. The add-to-project guide goes through the whole setup.

What to run, by stack ​

The first column of every table below is the name -f takes, and -f is repeatable. suss contract --from <source> reads a declared artifact, so there is no pack for one.

StackWhat to run
ts-rest full-stack-f ts-rest, which reads the provider and the client through the contract
Hono and fetch-f hono -f fetch
Express and fetch-f express -f fetch
Next.js route handlers-f nextjs
React and GraphQL-f react -f apollo-client
Lambda and SQS-f aws-sqs -f node, and contract --from cloudformation
BullMQ workers and the code that adds jobsadd -f bullmq
Cloudflare Worker-f cloudflare-workers, and contract --from wrangler
Postgres through Prismaadd -f prisma, and contract --from prisma
Postgres through Drizzleadd -f drizzle
MongoDB through Mongooseadd -f mongoose
NestJS with TypeORM repositoriesadd -f typeorm

Frameworks ​

A framework pack finds the units a framework defines: a route handler, a component, a resolver, a queue consumer. Run one of these and suss extract has something to describe.

NameWhat it readsCoverage
activejobActiveJob jobs and ActionMailer messages (Ruby): each job's perform and each mailer method is a consumer of an activejob channel, and perform_later or deliver_later a send to it.
apolloApollo Server resolvers (code-first).
aws-lambdaAWS Lambda HTTP handlers, paired with the routes a SAM template or serverless.yml declares.
aws-lambda-pythonAWS Lambda handlers written in Python, found from the Handler a SAM template or serverless.yml gives each function.
aws-lambda-rubyAWS Lambda handlers written in Ruby, found from the Handler a SAM template or serverless.yml gives each function, including a class method written file.Module::Class.method.
bullmqBullMQ workers and queues: each worker's processor is a consumer on its queue, and each add to a queue is a message send on it.
celeryCelery tasks (Python). A function under @app.task or @shared_task is the consumer of its task, and .delay, .apply_async and send_task are sends to it, so a route that enqueues a task reaches what the task does.
cloudflare-workersA Cloudflare Workers entrypoint: one unit per trigger the default export defines, and the bindings its code reads off the argument they arrive in.
expressExpress handlers.
fabricationFabrication builds in tests (Ruby), typed by the class each fabricator builds, so a test's calls on them are followed.
factory-botfactory_bot builds in tests (Ruby), typed by the class each factory builds, so a test's calls on them are followed.
fastapiFastAPI routes (Python). The verb comes from the decorator's attribute name, APIRouter prefixes are composed one include_router hop deep, and response_model and status_code are taken as the declared contract.
fastifyFastify handlers.
flask-restxflask-restx Resource routes (Python), including a project's own wrapper module that re-exports the route decorator.
graphql-rubygraphql-ruby class-based field DSL (Ruby). The pack follows mutation: and resolver: wiring to the referenced class, wherever the run declares it, and reads its arguments, its payload, its resolve method and the ready? and authorized? hooks that run first. It follows resolver_method: to the type's own method. Each path through that method records what the field returns, from its declared type with null where the schema allows it and the object type's fields, and the errors it raises or returns. It also records the model a resolver reads through dataloader, when a storage pack in the run recognizes that model.
honoHono handlers, including the c.json(body, status) argument order.
minitestMinitest and Rails test cases (Ruby), named by class and test method, so a PRD scenario can say which test covers it.
nestjs-graphqlNestJS GraphQL resolvers.
nestjs-microservicesNestJS microservice handlers: @EventPattern and @MessagePattern consumers on the channel the decorator states.
nestjs-restNestJS REST controllers.
nextjsNext.js route handlers, pages and server actions. The route comes from where the file is on disk, and a "use server" function becomes an action unit.
package-exportsThe boundary between packages in one workspace: public exports on the provider side, and imports of them on the consumer side. The pack reads the workspace manifest, so nobody has to list the packages for each project.
pytestpytest tests (Python), named by their node ids, so a PRD scenario can say which test covers it.
railsRails controller actions (Ruby), bound to the method and path config/routes.rb gives each one. An action the routes file does not reach is still discovered, with no boundary. The YAML files under config/ that Rails renders through ERB at boot are read as code that runs when the app loads.
reactReact function components, event handlers and useEffect bodies.
react-queryTanStack Query hooks. The pack links a component to the query function that its useQuery or useMutation call runs.
react-routerReact Router loaders, actions and routes.
rspecRSpec examples, named by their group titles, so a PRD scenario can say which test covers it.
sidekiqSidekiq jobs (Ruby): each job's perform is a consumer of a sidekiq channel, and perform_async, perform_in or perform_at a send to it.
ts-restts-rest handlers and clients, and the contract both sides are built from.
vitestvitest cases, named by their titles, so a PRD scenario can say which test covers it.

Clients ​

A client pack finds the call sites on the other side and binds each one to the method and path it sends. The checker uses that binding to pair a call with whatever serves the route.

NameWhat it readsCoverage
aiohttpaiohttp call sites (Python): the request methods on a ClientSession, opened with async with or held in an assignment.
apollo-client@apollo/client hooks and imperative client.query calls.
axiosaxios call sites, including calls on a client that axios.create made.
faradayFaraday call sites (Ruby): a request method on the module itself or on a connection Faraday.new built, served under the path that connection's own URL states.
fetchGlobal fetch call sites.
httpxhttpx call sites (Python): the verb functions, httpx.request, and a Client or AsyncClient held in an assignment or opened with with.
net-httpNet::HTTP call sites (Ruby): the module methods that send on their own, and a request object built with Net::HTTP::Get and its siblings, with the URL read through URI.
requestsrequests call sites (Python): the seven verb functions, requests.request, and a Session, each bound to the method and path the call states.

What your code reaches ​

An effects pack reads the calls inside a unit another pack discovered: a query, a publish, a read of the environment. On its own it comes back empty, so run it alongside the pack that finds the units.

NameWhat it readsCoverage
activerecordActiveRecord calls (Ruby): a call matches when its method is one ActiveRecord defines as a read or a write and the class behind its receiver reaches ActiveRecord::Base, following what each class extends through the project. Statements the project wrote itself are read for the tables they touch, whether they went through find_by_sql and count_by_sql or through the connection. A write also runs the model's callbacks, and what they reach is recorded on the body that did the write.
aws-dynamodbAWS SDK v3 DynamoDB calls. Each one becomes a storage-access interaction.
aws-eventbridgeAWS EventBridge PutEvents producer calls. Each one becomes a message-bus interaction.
aws-s3AWS SDK v3 S3 object calls. Each one becomes a storage-access interaction.
aws-secrets-managerAWS Secrets Manager calls. Each one becomes a storage-access interaction on the secret.
aws-snsAWS SDK v3 SNS Publish and PublishBatch calls. Each one becomes a message-send interaction on the topic.
aws-sqsAWS SDK v3 SQS producer calls. Each one becomes a message-send interaction.
aws-ssmAWS SSM Parameter Store calls. Each one becomes a storage-access interaction on the parameter.
bigqueryBigQuery queries and table calls. Each one becomes a storage-access interaction scoped to its dataset.
bigquery-pythonBigQuery calls (Python). The statement a client or an Airflow hook is handed is read for the tables it touches. Calls such as get_table and insert_rows take a table name instead of SQL, and that name is read too.
bigquery-rubygoogle-cloud-bigquery calls (Ruby): a call matches when its receiver follows back to a client the gem handed out, and the statement it was given is parsed for the tables it touches.
drizzleDrizzle ORM query-builder and relational-query calls. Each one becomes a storage-access interaction on the SQL table it touches.
gcsGoogle Cloud Storage calls. Each one becomes a storage-access interaction.
mongooseMongoose model calls. Each one becomes a storage-access interaction on the collection that the model's .model(...) call declares.
nodeNode.js runtime primitives, scheduling and the process surface, each recorded as an interaction effect. A process.env.X or import.meta.env.X read, or a key of a schema parsed against either, becomes a config-read interaction. A module-loading global becomes a metadata-read interaction. A console call or a write to process.stdout or process.stderr becomes a stream-write interaction on the stream it goes to.
pgnode-postgres queries. Each one becomes a storage-access interaction on the tables its statement touches.
pg-rubypg gem calls (Ruby): a call matches when its receiver follows back to a connection the gem handed out, and the statement it was given is parsed for the tables it touches.
prismaPrisma client calls. Each read and each write becomes a storage-access interaction.
redisRedis, Valkey and node-redis commands. Each one becomes a storage-access interaction.
sqlalchemySQLAlchemy calls (Python). The pack declares which types a query returns and which methods write. The adapter matches a call chain by following a project's own base class to the method behind the call, and reads that method's declared return type.
sqlmodelSQLModel calls (Python). The pack declares which types a query returns and which methods write, under the modules SQLModel exports them from. It also includes the SQLAlchemy patterns, since a SQLModel project reaches those too.
typeormTypeORM repositories that NestJS injects with @InjectRepository. Each read and write becomes a storage-access interaction on the entity's table, and a query on an injected data source or entity manager is read as SQL.
zustandzustand stores: setState writes and getState reads against the store as a client-side container.

Contract sources ​

These are not packs. A contract source reads something the project already declares and writes the same summaries the extractor writes, and you reach it through suss contract --from <name>. Contract sources shows a command and its output for each one.

Reader--fromWhat it readsCoverage
@suss/contract-openapiopenapiAn OpenAPI 3.x document, JSON or YAML.
@suss/contract-graphqlgraphql, graphql-documentsA GraphQL SDL file becomes one resolver-kind summary per Query, Mutation and Subscription field. Committed .graphql and .gql operation documents become one client-kind summary per operation, with fragment spreads inlined, so a repo that keeps its queries in files pairs against its resolvers without any call site being traced.
@suss/contract-cloudformationcloudformationCloudFormation and SAM templates. It delegates to the OpenAPI and API Gateway readers, and handles SQS event-source mappings and a function's Environment itself.
@suss/contract-serverlessserverlessA Serverless Framework service file. The reader rewrites the functions block in SAM's form and passes it to the CloudFormation reader, so a route, a queue consumer or an environment contract comes out the same whichever manifest language declared it. ${self:} resolves against the document, and a deploy-time reference keeps its token.
@suss/contract-terraformterraformA .tf file or the directory a module lives in. The AWS and Google Cloud provider vocabularies both load.
@suss/contract-wranglerwranglerA Cloudflare Worker's wrangler.toml or wrangler.jsonc. The Worker comes out as a deployable with its configuration, values included, so a store addressed through a variable resolves. The reader also writes a summary for each KV namespace, R2 bucket, D1 database and Queues channel the Worker is bound to.
@suss/contract-appsyncappsyncAn AppSync GraphQL schema and its resolver mapping templates.
@suss/contract-prismaprismaA schema.prisma file, one storage provider summary per model.
@suss/contract-storybookstorybookStorybook CSF3 stories, one component contract summary per story.
@suss/contract-aws-apigateway(through the readers above)API Gateway resource semantics for REST and HTTP APIs, including the transitions the platform injects. The CloudFormation, Serverless and Terraform readers all delegate to it.
@suss/contract-intent(through check --intent)Team-authored intent specs, *.intent and *.prd.

Asking for a pack ​

If the framework you use is not in a table above, open an issue with the library, a link to its docs, and ten or fifteen lines of code showing how your project registers a handler and returns a response. A pack is written from that material, and a snippet from a project that uses the library settles questions the library's own docs leave open.

You do not have to wait for one. A pack is a data object of about a hundred lines that can live in a package of your own, and -f @your-scope/your-pack loads it with nothing else to configure. Write a pack goes through building one from start to finish.

If a pack exists and comes back with nothing, that is a different problem: Fix a run that found nothing.

Everything else in the box ​

@suss/cli also installs the IR the summaries are written in, the language adapters, the checker, and the shared code the packs run on.

combined

PackageWhat it isCoverage
@suss/ir-coreShared IR primitives, type shapes, boundary bindings + constructors, source locations, confidence. Base for behavioral-ir and intent-ir.
@suss/behavioral-irzod schemas, types, parsers, and generated JSON Schema. Install this to consume summaries.
@suss/intent-irTeam-authored intent: system intent (what a boundary should do) + PRD outcome intent, paired against derived summaries.
@suss/datalogSmall semi-naive Datalog evaluator with stratified negation; the rules engine behind derived program facts.
@suss/resolutionDatalog rules for following a value back to the function it resolves to: a factory's argument, a re-exported wrapper, a closure three levels down. Language-neutral, so an adapter supplies facts and inherits the rules.
@suss/valuesBounded evaluator over an abstract value domain: strings as pieces with named holes, sequences, records. An adapter supplies a lowering of its AST and a row table for its operators and library methods, and readers ask what an expression is worth instead of matching one spelling at a time.
@suss/extractorAssembly engine. It converts raw extracted structure into BehavioralSummary.
@suss/recognizeWrite a pack as data: a chain of named links, compiled to the recognizer hooks, run by any adapter that implements the executor ops.
@suss/packsEvery pack, one subpath each, so @suss/packs/express reaches the Express pack. The CLI resolves -f names to these on its own.tested through each pack
@suss/adapter-typescriptTypeScript language adapter via ts-morph.
@suss/adapter-pythonPython language adapter: tree-sitter (WASM) parsing, a lexical binder, repo-scoped module resolution. v0, no path-engine work yet.
@suss/adapter-rubyRuby language adapter: tree-sitter (WASM) parsing, a lexical binder over class/module nesting, Rails' constant-to-path convention for mutation: / resolver: wiring and controller discovery. v0, graphql-ruby and rails, no path-engine work yet.
@suss/checkerPairwise cross-boundary checker (behavioral).
@suss/checker-intentPairs team-authored intent against derived code; emits IntentFinding coverage.
@suss/cliCLI wrapper.
@suss/mcpAn MCP server over the CLI, so a coding agent can ask about a boundary while it works. It keeps its summaries current as files change.
@suss/sqlReads what a SQL statement touches, for packs that find a raw query.
@suss/manifest-awsParses CloudFormation and SAM templates into a shared facts layer that the contract readers and the manifest-driven framework packs both read.
@suss/terraform-awsWhat AWS's Terraform provider declares, as data for that reader.
@suss/terraform-gcpWhat Google Cloud's Terraform provider declares, as data for that reader.

Released under the Apache-2.0 License.