sashimi
Thinly sliced Poisson: a maintained wrapper around APBS for biomolecular electrostatics.
[!WARNING] This is a work in progress. It is not ready to be depended on.
sashimi-electro0.1.0 is on PyPI so the work can be installed and read, not because it is finished. Concretely:
- This is an alpha. 0.1.0 is the first upload, there is no support, and the changelog starts there.
- Interfaces change without notice. There is no deprecation period and no compatibility promise between any two releases.
- The numbers in here are research notes, not validated results. They are measured and they are recorded honestly — including the ones that turned out to be wrong, which are left in with their corrections — but none of it has been reviewed by anyone but its author.
- Whole phases of ROADMAP.md are unbuilt, and the shipped protocol knowingly diverges from the target in §4.1.
Do not use this for science you intend to publish, and do not build anything on top of it yet. If it is useful to you anyway, treat it as a starting point you have adopted rather than a dependency you can expect to be maintained for you.
It is distributed as sashimi-electro and imported as sashimi — the
plain sashimi name on PyPI belongs to an unrelated, dormant library, so the
install name and the import name differ.
Computes electrostatic potential maps and polar solvation energies from charged structures, using the APBS 3.4.1 binary as its solver backend. APBS is never vendored, patched, or built from source — it comes from your system package manager.
from sashimi import FiniteDifferenceRequest, GridSpec, SolventModel
from sashimi.apbs import ApbsSolver
from sashimi.pqr import read_pqr
result = ApbsSolver().solve(
FiniteDifferenceRequest(
structure=read_pqr("protein.pqr"),
solvent=SolventModel(ionic_strength=0.15),
grid=GridSpec(resolution=0.5, padding=10.0),
)
)
print(result.energy_kj_mol) # -1234.5 (kJ/mol)
print(result.provenance.summary()) # apbs-3.4.1 sha256:83acdfb0818a
result.potential.to_dx("potential.dx") # load in PyMOL / ChimeraX
result.potential.value_at([[12.0, 3.4, -1.0]])
The request type is per solver family: a FiniteDifferenceRequest carries a
grid, a BoundaryElementRequest carries a mesh density and no grid at all, so a
request a backend cannot honor is unrepresentable rather than merely rejected.
Install
pip install sashimi-electro # or: uv add sashimi-electro
That is the whole install for debye, the built-in solver, along with
pdb2pqr and the MCP server — all pure Python, nothing to fetch by hand. If
debye is the backend you want, stop here and read
"A faster debye"
below.
APBS is a second step, because it is a compiled binary that no Python installer can provide. Platform wheels that would collapse this to one command are phase 6 of ROADMAP.md and are not built yet. Install it from your system package manager:
# Recommended — same channel and build CI tests against, linux-64 and osx-arm64
micromamba create -n apbs -c conda-forge apbs=3.4.1
export SASHIMI_APBS_PATH="$(micromamba run -n apbs which apbs)"
Any conda-family tool works for that (conda, mamba, pixi); it manages
nothing Python here, it just fetches one binary. If you would rather use a
system package manager:
brew tap brewsci/bio && brew install brewsci/bio/apbs # macOS, native arm64
sudo apt install apbs # Ubuntu 24.04+ / Debian 12+ (22.04 has only 3.0.0)
Both work, but neither is as well-governed: APBS is not in homebrew-core —
brewsci/bio is a third-party tap that recent Homebrew refuses to load without
an explicit trust step — and Debian's build differs observably from it. CI
therefore tests the conda-forge build on both platforms.
That difference is real and worth knowing: Debian's APBS is MPI-enabled and
writes its grid as potential-PE0.dx, where the Homebrew and conda-forge
builds write potential.dx. Same version, same input, same contents.
sashimi.apbs.run.find_potential accepts either.
SASHIMI_APBS_PATH overrides binary discovery; otherwise which apbs wins,
with an active conda environment as a fallback.
From a clone, to work on it
uv sync # creates .venv from uv.lock
uv run pytest # full suite
uv run pytest -m "not apbs" # skips everything needing the binary
If you are doing real electrostatics with debye, install the extra
debye — the built-in solver that needs no binary at all — is three to four
times faster with sashimi-electro[fast], and you probably want it if you are
working on proteins rather than peptides.
pip install 'sashimi-electro[fast]' # or, from a clone: uv sync --all-extras
It is an extra rather than a dependency because it is large: ~145 MB, since it pulls in numba and llvmlite — several times the size of everything else here combined. That is a real cost on a laptop, in a container image and in CI, and it is not a decision to make on your behalf when many callers solve one small structure and never notice the difference.
What it buys, and where. Nearly all of a debye solve is geometry — building
the solvent-excluded surface and then classifying grid points against it — and
the extra swaps six loops for compiled ones: the three classification families
(9x, 17x, 28x) and the three construction steps that feed them (6-10x on the
probe seats, ~12x on the rims, and 93-116x on the neighbour search, which was a
numpy call per candidate atom pair). Measured on this machine, CPU seconds at
1.0 Å, interleaved and best of three:
| structure | pure numpy | with the extra | |
|---|---|---|---|
| fas2, 59 residues | 5.82 s | 1.39 s | 4.19x |
| actin monomer, 382 residues | 62.52 s | 18.86 s | 3.31x |
| serum albumin, 1,156 residues | 155.21 s | 45.99 s | 3.37x |
Two earlier versions of this section overstated it and then understated it. It first said a 1,156-residue solve went from two and a half minutes to about half a minute, which was a projection from a per-loop speed-up rather than a measurement; correcting that gave 1.73x, which was true of a build where only the classification loops were compiled. The table above is the current one.
It changes nothing else: the energies are bit-identical either way, which
tests/test_debye_kernel.py asserts loop by loop on real geometry rather than
assuming, and CI runs the pure-numpy path on two of its three legs and the
compiled one on the third.
If you are unsure whether you have it, sashimi_capabilities reports
acceleration.compiled_surface_kernel and, when it is missing, says so in one
sentence. SASHIMI_NO_NUMBA=true turns it off without uninstalling anything (1, yes
and on work too; false, 0, no and off leave it on).
Nothing else in sashimi is affected — APBS, DelPhi, TABI-PB and gb do not use
it, and debye is correct without it, only slower.
Both package managers above ship exactly the 3.4.1 this project is frozen
against — but unlike a lockfile, neither holds it there. tests/test_corpus.py
is what replaces that pin: it asserts the discovered version and re-solves the
Born ion against checked-in energies and probe values. If a brew upgrade
moves APBS underneath you, that test tells you in kJ/mol. Regenerate the corpus
deliberately with sashimi corpus build --force — never to turn a red test green.
Development
uv run pre-commit install # once, per clone
uv run pytest && uv run ruff check . && uv run mypy
Ruff and mypy (strict) run as pre-commit hooks and again in CI, both through
uv run, so the hook and CI use the one version pinned in uv.lock — there is
no second set of tool versions to drift. The binary-free test tier runs on
push; CI runs the full suite including the APBS-marked tests.
Repository settings
Two settings the checked-in workflows depend on, neither of which lives in the repo:
- Settings → General → Allow auto-merge. Without it, the Dependabot
auto-merge workflow fails at
gh pr merge --auto. - A ruleset on
mainrequiring theci-okstatus check. This is what makes auto-merge wait.ci-okis a single job gating the whole matrix, so the required check name stays stable when the matrix changes.
Both are configured on this repository. They need a public repository or a
paid plan; on a private repo on the Free plan the ruleset API returns 403 and
allow_auto_merge silently stays false.
If either is ever missing, the auto-merge workflow skips with a warning rather
than merging. That guard is not decoration: gh pr merge --auto does not
fail when auto-merge is unavailable — it merges the PR immediately, ignoring
CI. PR #1 landed on main with a red build exactly that way.
Dependabot covers GitHub Actions and the uv ecosystem, which updates
pyproject.toml and uv.lock in the same commit. It does not cover APBS —
no ecosystem tracks system packages — which is what tests/test_corpus.py
guards instead.
Layers
sashimi.protocol is the load-bearing boundary. Above it everything speaks
physics — angstroms, molar ionic strength, dielectric constants, kT/e, kJ/mol.
Below it, sashimi.apbs speaks APBS — dime, cglen, fglen, srfm. A
future native solver implements Solver and replaces only the bottom layer, so
no APBS concept may leak upward.
Scope is deliberately narrow: the mg-auto finite-difference path with the
linearized PBE. The FEM, geoflow, BEM, PBAM and PBSAM solvers are not exposed,
and there is no raw APBS-input passthrough — that would defeat the abstraction.
sashimi.delphi is the second backend, and the test of whether that boundary
was real. It required no protocol change at all, absorbing a cubic grid, a
Gaussian-cube map in Bohr, energies in kT and a temperature parameter in
Celsius below the same Solver interface.
sashimi.tabipb is the harder test. It is a boundary-element solver: no
grid at all, and its answer is a potential on a triangulated dielectric
interface rather than a volume. That is the split the protocol was shaped around
— BoundaryElementRequest and SurfacePotential were designed in phase 4 for a
solver that did not exist yet — and it too needed no change. Three solvers
across two families agree on ALA-GLY to 2.08%, with the boundary-element
answer falling between the two finite-difference ones.
A BEM backend answers different questions, and sashimi says so rather than
pretending otherwise: there is no volume to interpolate, so sashimi_potential_at
does not apply, and a single-sphere solute cannot be triangulated at all.
sashimi.gb is the odd one out twice over. It is a Generalized Born
approximation rather than a discretization of the equation, and it runs in
this process — no binary, no environment variable, nothing to install, so it
is the one backend that cannot be missing. Roughly 300 lines of numpy: hen
lysozyme in 0.196 s against APBS's 6.79 s, landing 1.48% from the APBS/DelPhi
consensus.
Being an approximation is declared, not implied. AccuracyTier in provenance
says so, and sashimi validate reports it separately rather than averaging it
into the spread — otherwise the tolerance would have to be wide enough to
accommodate an approximation, which is wide enough to hide a real regression in
the solvers being compared.
Two things about it are worth knowing before using it:
- It answers on the molecular surface, though its integral runs over van der Waals spheres. The rescaling exists to carry one onto the other. Declared the intuitive way it sits 31% from APBS instead of 4.7%.
- It substitutes mbondi radii by default. pdb2pqr emits Lennard-Jones radii,
including exactly 0 for hydroxyl hydrogens — fine for a grid solver, an
infinite self-energy for a method that divides by radius. Using them as given
costs 35% on a protein. The substitution is counted in the result's
diagnostics, and
GbRadii.AS_GIVENturns it off.
sashimi.debye is the clean-room solver, and the point of it is the
combination: it needs no binary and it is in the reference tier. gb
needs nothing installed but approximates the equation; every other backend that
discretizes it needs a compiled program. So on a machine with no APBS you get
real Poisson-Boltzmann rather than known-wrong physics — which is the gap that
reordered this roadmap, since the consumer it exists for has no binary
available.
About 2,000 lines of numpy: finite-volume flux balance with the dielectric
sampled at face centres, cloud-in-cell charge assignment, a Debye-Huckel
boundary on the box face, and multigrid-preconditioned CG whose coefficients are
re-discretized from the geometry at each level. It solves the linearized
equation on the van der Waals and solvent-excluded boundaries, and declines
smoothed-molecular and gaussian on purpose — those are APBS's harmonic
averaging and DelPhi's Gaussian dielectric, and reproducing them would be
claiming another code's discretization rather than the equation. corpus verify
reports the cases it declines as refusals rather than as gaps.
It is graded against the incumbents rather than against a round number: 0.85% from the Born closed form, within 1.5% of the Kirkwood series, and on the solvent-excluded surface it sits between DelPhi C++ and APBS on all twelve real structures measured from 906 to 8,279 atoms.
Using DelPhi
Neither DelPhi flavour has a package, so both are opt-in and neither is a dependency:
# the C++ reference build — compile from the Clemson tarball, then:
export SASHIMI_DELPHI_PATH=/path/to/delphicpp_release
# or the same lab's pure-Python reimplementation, which installs anywhere
uv venv --python 3.13 .pydelphi
uv pip install --python .pydelphi/bin/python git+https://github.com/shaileshp51/pyDelPhi
export SASHIMI_DELPHI_PATH="$PWD/.pydelphi/bin/pydelphi-static"
pyDelPhi is driven as a subprocess and never imported: it is AGPL-3.0 where
sashimi is MIT, and that is the boundary APBS already sits behind. The C++ build
is faster and additionally supports a van der Waals boundary; pyDelPhi needs no
compiler and runs anywhere, including linux-aarch64, where no APBS exists.
The backends do not agree about which surface models exist, and surfacing
that is the most useful thing a second backend does. sashimi_capabilities
reports which models the installed backends actually share, because a spread
computed across mismatched surface definitions is a modelling difference
misreported as a solver disagreement. All five shipped backends share
molecular, which is why it is the default; smoothed-molecular is APBS-only,
so a solve that asks for it refuses on the other four rather than silently
substituting, and van-der-waals is APBS, DelPhi and debye only. On the models
they share, APBS and DelPhi agree to 2.4% on hen lysozyme.
See ROADMAP.md for the full design and phasing.
Status
Phases 0–4, 5 and 7 are done — 0.1.0 is the phase 5 release. The core library is validated against the closed-form Born ion, converging monotonically as the grid refines (0.62% → 0.11% → 0.02% at 0.41 / 0.20 / 0.16 Å spacing).
Five backends now span three solver families — finite difference, boundary element, analytic — and the protocol absorbed all five without changing shape: two enum members, no new types. They agree on ALA-GLY to 3.65% across families, and on hen lysozyme to 1.97%.
Two of the five need nothing installed, and since they share a surface model
you can cross-validate on a machine with no APBS, no DelPhi and no mesher.
sashimi.debye is the newer one: a clean-room finite-difference solver in numpy
that discretizes the linearized Poisson-Boltzmann equation rather than
approximating it, on the van der Waals and solvent-excluded boundaries.
The MCP server exposes nine tools over stdio:
| Tool | Question it answers |
|---|---|
sashimi_capabilities |
what can this installation do? |
sashimi_validate_inputs |
would this solve work, and what would it cost? |
sashimi_prepare_structure |
PDB → PQR, and what did pdb2pqr rebuild? |
sashimi_solve |
the potential map and solvation energy |
sashimi_potential_at |
the potential at these coordinates |
sashimi_potential_extrema |
where are the strongest patches? |
sashimi_potential_in_sphere |
what is the field in this pocket? |
sashimi_residue_potentials |
which residues sit in negative potential? |
sashimi_compare_maps |
how do two maps differ? |
Run it with sashimi-mcp, or register it:
{ "mcpServers": { "sashimi": { "command": "uv",
"args": ["run", "--project", "/path/to/sashimi", "sashimi-mcp"] } } }
The golden corpus is a first-class feature:
sashimi corpus verify # the standard tier, diffed against record
sashimi corpus verify --tier full # all 98 cases
sashimi corpus build --force # re-record, deliberately
Ninety-eight cases, summaries in tests/corpus/, split by measured wall time
into fast (what pytest runs), standard (a CI step per push) and full (on
demand). It is the regression net for the unpinned APBS, and it is the
acceptance gate the clean-room solver was held to: sashimi corpus verify --backend debye needs no APBS installed, and passes.
Many of those cases are on a surface model more than one solver supports, so
they carry answers from more than one backend: tests/corpus/delphi/ holds
fifty-six, tests/corpus/debye/ fifty-six from the clean-room solver,
tests/corpus/gb/ thirty from the in-process Generalized Born tier, and
tests/corpus/tabipb/ six from the boundary-element one. No backend answers
the whole corpus — debye declines APBS's harmonic averaging and DelPhi's
Gaussian dielectric by name, and corpus verify reports those as refusals
rather than as gaps. Comparing
those files against tests/corpus/ needs no binary at all, which is where the corpus says something
neither recording could alone — the two reference-tier families agree to
1.0–1.6%, and the approximate tier ranges from 0.7% to 28%.
With two backends installed, they can be checked against each other:
sashimi validate # the fast tier, every installed backend
sashimi validate --tier full # every case; tens of minutes with five backends
sashimi validate --case lysozyme-molecular # a named case, whatever tier it is in
sashimi validate --backend apbs --backend delphi --surface molecular
ok born-ion-coarse 3 backends agree: 2.30% spread (-234.000 to -228.609 kJ/mol,
tolerance 10%); approximations as documented from the
reference: gb 1.76% (tolerance 15%)
apbs -234.000 kJ/mol (polar-solvation)
delphi -228.609 kJ/mol (polar-solvation)
gb -235.681 kJ/mol (polar-solvation) [approximate, 1.76% from reference]
debye -232.213 kJ/mol (polar-solvation)
not asked: tabipb — tabipb needs at least 4 atoms to triangulate a surface and this structure has 1
same system as born-ion-molecular, born-ion-vdw once the molecular surface is applied — solved once
Two lines there are the point of the tool. not asked means that backend
declined this system and the others were compared without it — a boundary
element solver has no mesh for a one-atom solute, and that is not a reason to
throw away the answers of the four solvers that do. same system as means
the named cases differ only in a surface model that validate had to override
to compare across backends, so they are one question and were solved once;
without that line their identical energies read as a measurement.
validate exits non-zero when any compared case disagrees, which on a
fully-installed machine today means peptide-low-solvent-dielectric: the three
finite-difference backends land within 1.8% while TABI-PB reads 19.4% away and
gb 46.6%. That is a real result about a low solvent dielectric, not a broken
install. A case is only SKIPped when fewer than two backends can take it, or
when one crashes on a structure it had accepted.
Most of validate is about refusing to answer. A spread only means "the
solvers disagree" if the surface model, the equation and the reported energy
term were all held fixed, and none of those differences shows up in the number.
That last one is not hypothetical. DelPhi's headline energy is the polarization term alone, where APBS's is a difference against an ion-free reference and so carries the mobile-ion atmosphere; they coincide only at zero salt. sashimi asks the C++ DelPhi for the matching quantity instead of comparing the two — but pyDelPhi cannot report it, so with that flavour installed a salted comparison is refused, and says why.
Energies are compared directly, potentials by sampling both maps at the same physical coordinates, since two backends never produce the same grid.
Choosing a backend by what you want, not by name
sashimi_solve takes prefer as well as backend, for the caller who knows
what they want from the answer but not which program gives it:
| leads with | why | |
|---|---|---|
fast |
APBS | 12.4 s where pyDelPhi is 27.3 s at 1,156 residues, and it answers every surface model |
stable |
pyDelPhi | least sensitive to where the lattice falls — 0.15–0.52% under rigid rotation against APBS's 0.42–1.07%, measured on a coarser grid in every comparison |
portable |
debye | ships with sashimi, no install step; the only option on linux-aarch64, where conda-forge has no APBS |
It resolves against what is installed and what the request needs. pyDelPhi
has no van der Waals boundary, so prefer="stable" on one falls through to
DelPhi C++ and the result says so in selected_because. Naming backend
explicitly always wins. sashimi_capabilities prints the whole table for the
machine it is on.
stable, not accurate — above a two-atom solute nothing here has a
reference answer, so what is measured is how little the answer moves when the
solute is rotated, which is discretization noise and not distance from truth.
The two DelPhi builds are separately addressable as delphi-cpp and pydelphi;
delphi still means whichever one is installed.
Measuring a change to the solver
debye runs in this process, so it is the one backend whose speed is sashimi's
own problem. sashimi bench is the instrument its performance claims are made
on, and every part of it is a reaction to a measurement that lied:
sashimi bench --structure tests/data/apbs-examples/fas2.pqr
sashimi bench --structure tests/data/apbs-examples/fas2.pqr --against ../sashimi-main
sashimi bench --structure tests/data/apbs-examples/fas2.pqr --backend apbs
--backend times any installed solver, not only debye, and CPU time
includes subprocesses — time.process_time() cannot see a child, so timing APBS
or DelPhi without getrusage(RUSAGE_CHILDREN) measures nothing but this
process's bookkeeping. That is how every backend row in ROADMAP.md §12 is
produced. Two caveats it will tell you about: --resolution means nothing to
gb, which discretizes nothing, or to tabipb, whose cost knob is mesh
density; and on a platform without POSIX resource the command warns that
subprocess time is not being counted.
Wall clock cannot measure this. Interleaved on one machine, alternating
between two revisions of the same case, identical code read 61.8 / 79.1 /
42.5 s against 52.2 / 44.6 / 60.5 s — a 1.9x spread with the ranges overlapping
completely. That is other processes taking wall-clock time away from the run,
which does not change how many CPU-seconds the work costs. So bench reports
CPU time, takes the minimum of N rather than a mean, and with
--against interleaves the two revisions one sample at a time so that a
drift in machine state lands on both. The same pair that read as a 40%
regression on wall clock reads 44.96 s against 42.04 s here.
--against takes any checkout of this repository — a git worktree at the
revision you are comparing to. It runs there with that tree's own lockfile, and
it does not require the baseline to contain sashimi bench, which would
make every revision before this one unmeasurable.
The energy is part of the measurement. A solver can be made arbitrarily fast
by computing something else, so both sides report their energy to full precision
and bench exits non-zero when they differ. An answer-preserving change is held
to bit-identical, not to a tolerance — which is the bar the batched surface
work in M7 has to meet.
Released as sashimi-electro 0.1.0. See ROADMAP.md for where
this is heading — it is the single planning document, covering the protocol, the
multi-backend future, distribution and debye.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sashimi_electro-0.1.0.tar.gz.
File metadata
- Download URL: sashimi_electro-0.1.0.tar.gz
- Upload date:
- Size: 2.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b30573c3bccbcb6204d0ec039c70c54cf0f166e2cf66778fd68be259c28dbc2f
|
|
| MD5 |
9c80df8fc21a9bcde17b62cd6cee0886
|
|
| BLAKE2b-256 |
4a94748edb45a6e0f71bf0caa5325be4d973a551394623dd8d4b13a1bcb54697
|
Provenance
The following attestation bundles were made for sashimi_electro-0.1.0.tar.gz:
Publisher:
release.yml on chemrich/sashimi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sashimi_electro-0.1.0.tar.gz -
Subject digest:
b30573c3bccbcb6204d0ec039c70c54cf0f166e2cf66778fd68be259c28dbc2f - Sigstore transparency entry: 2620832065
- Sigstore integration time:
-
Permalink:
chemrich/sashimi@d9a8910dd167201165d90e416ef3db5bc0914eae -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/chemrich
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d9a8910dd167201165d90e416ef3db5bc0914eae -
Trigger Event:
push
-
Statement type:
File details
Details for the file sashimi_electro-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sashimi_electro-0.1.0-py3-none-any.whl
- Upload date:
- Size: 290.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eac43cc46859e3aa3cf55899964f52c235e09ccfd0726ae005e99db138d2ae8
|
|
| MD5 |
c543e3ab7e3e32ca3232af0adf95e3c3
|
|
| BLAKE2b-256 |
e96ab37f14a504cef844f7a22b1c3f28ed9ee7b1d7312c831c5ddb8a97ef5bec
|
Provenance
The following attestation bundles were made for sashimi_electro-0.1.0-py3-none-any.whl:
Publisher:
release.yml on chemrich/sashimi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sashimi_electro-0.1.0-py3-none-any.whl -
Subject digest:
4eac43cc46859e3aa3cf55899964f52c235e09ccfd0726ae005e99db138d2ae8 - Sigstore transparency entry: 2620832075
- Sigstore integration time:
-
Permalink:
chemrich/sashimi@d9a8910dd167201165d90e416ef3db5bc0914eae -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/chemrich
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d9a8910dd167201165d90e416ef3db5bc0914eae -
Trigger Event:
push
-
Statement type: