Pytanque is a Python API for lightweight communication with the Rocq proof assistant via coq-lsp.
pet-server) for multi-client usage, stdio mode (via pet) for single-client simplicity, or HTTP mode (via rocq-ml-server) for inference at scale.First, install coq-lsp with the required dependencies:
# Install dependencies
opam install lwt logs coq-lsp
# Or install one of the dev versions of coq-lsp, e.g., for Coq.8.20
opam install lwt logs coq.8.20.0
opam pin add coq-lsp https://github.com/ejgallego/coq-lsp.git#v8.20
pip install git+https://github.com/llm4rocq/pytanque.git
We recommend using uv.
cd pytanque
uv sync
Pytanque supports three communication modes with the Petanque backend:
$ pet-server # Default port: 8765
# Or specify a custom port:
$ pet-server -p 9000
from pytanque import Pytanque
with Pytanque("127.0.0.1", 8765, mode=PytanqueMode.SOCKET) as client:
# Start a proof
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
You can quickly try this example with:
# Socket mode example
python examples/foo.py
See also the notebook examples/getting_started.ipynb for more examples.
For direct communication without a server, use subprocess mode:
from pytanque import Pytanque, PytanqueMode
with Pytanque(mode=PytanqueMode.STDIO) as client:
# Same API as socket mode
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
For communication with a rocq-ml-server.
See here for more details about startup arguments:
$ rocq-ml-server # Default port: 5000
# Or specify a custom port:
$ rocq-ml-server -p 9000
from pytanque import Pytanque
# When using HTTP mode, we can use the `timeout_http` attribute, corresponding to the maximum time the server has to answer before raising a timeout error. Useful when `number of clients` >> `number of pet servers`.
with Pytanque("127.0.0.1", 5000, mode=PytanqueMode.HTTP, timeout_http=20*60) as
# Same API as socket mode
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
start(file, theorem): Begin a proof sessionrun(state, command): Execute tactics or commandsgoals(state): Get current proof goalspremises(state): Get available premises/lemmasget_root_state(file): Get initial document statestate_equal(st1, st2, kind): Compare proof statesstate_hash(state): Get state hashtoc(file): Get table of contentsast(state, text): Parse command to ASTast_at_pos(file, line, char): Get AST at file positionget_state_at_pos(file, line, char): Get proof state at positionlist_notation_in_statement(state, statement): List the notations in a theoremAll commands return states with feedback containing Rocq messages:
state = client.run(state, "Search nat.")
for level, message in state.feedback:
print(f"Level {level}: {message}")
First install dev dependencies for testing:
uv sync --dev
You can launch all the tests with pytest. The test suite includes tests for both communication modes:
# Run all tests (socket + subprocess modes)
uv run pytest -v .
# Run only socket mode tests
uv run pytest tests/test_unit.py tests/test_integration.py -v
# Run only stdio mode tests
uv run pytest tests/test_stdio.py -v
Note: Socket mode tests require pet-server to be running. Subprocess mode tests require the pet command to be available in PATH.
The complete API documentation is available at: https://llm4rocq.github.io/pytanque
To build the documentation locally:
# Install documentation dependencies
uv sync --extra docs
# Build the documentation
cd docs
uv run sphinx-build -b html . _build/html
# Open the documentation
open _build/html/index.html
We use atdpy to automatically generate serializers/deserializers from protocol type definitions. These types definition should match the ocaml code of petanque in coq-lsp.
To add a new method:
protocol.atdatdpy protocol.atd to generate protocol.pyclient.py with the new methodSocket Mode Connection Errors
pet-server is running: pet-server -p 8765Subprocess Mode Errors
pet command is available in PATH: which petpet binarypet process can access your Rocq/Coq filesFile Path Issues
client.set_workspace()Installation Issues
pet and pet-serverlwt and logs before coq-lsp (required for both modes)pet --version and pet-server --versionPerformance Considerations
Python
100.0%
Pytanque is a Python API for lightweight communication with the Rocq proof assistant via coq-lsp.
pet-server) for multi-client usage, stdio mode (via pet) for single-client simplicity, or HTTP mode (via rocq-ml-server) for inference at scale.First, install coq-lsp with the required dependencies:
# Install dependencies
opam install lwt logs coq-lsp
# Or install one of the dev versions of coq-lsp, e.g., for Coq.8.20
opam install lwt logs coq.8.20.0
opam pin add coq-lsp https://github.com/ejgallego/coq-lsp.git#v8.20
pip install git+https://github.com/llm4rocq/pytanque.git
We recommend using uv.
cd pytanque
uv sync
Pytanque supports three communication modes with the Petanque backend:
$ pet-server # Default port: 8765
# Or specify a custom port:
$ pet-server -p 9000
from pytanque import Pytanque
with Pytanque("127.0.0.1", 8765, mode=PytanqueMode.SOCKET) as client:
# Start a proof
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
You can quickly try this example with:
# Socket mode example
python examples/foo.py
See also the notebook examples/getting_started.ipynb for more examples.
For direct communication without a server, use subprocess mode:
from pytanque import Pytanque, PytanqueMode
with Pytanque(mode=PytanqueMode.STDIO) as client:
# Same API as socket mode
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
For communication with a rocq-ml-server.
See here for more details about startup arguments:
$ rocq-ml-server # Default port: 5000
# Or specify a custom port:
$ rocq-ml-server -p 9000
from pytanque import Pytanque
# When using HTTP mode, we can use the `timeout_http` attribute, corresponding to the maximum time the server has to answer before raising a timeout error. Useful when `number of clients` >> `number of pet servers`.
with Pytanque("127.0.0.1", 5000, mode=PytanqueMode.HTTP, timeout_http=20*60) as
# Same API as socket mode
state = client.start("./examples/foo.v", "addnC")
print(f"Initial state: {state.st}, finished: {state.proof_finished}")
# Execute tactics step by step
state = client.run(state, "induction n.", verbose=True)
state = client.run(state, "auto.", verbose=True)
# Check current goals
goals = client.goals(state)
print(f"Current goals: {len(goals)}")
start(file, theorem): Begin a proof sessionrun(state, command): Execute tactics or commandsgoals(state): Get current proof goalspremises(state): Get available premises/lemmasget_root_state(file): Get initial document statestate_equal(st1, st2, kind): Compare proof statesstate_hash(state): Get state hashtoc(file): Get table of contentsast(state, text): Parse command to ASTast_at_pos(file, line, char): Get AST at file positionget_state_at_pos(file, line, char): Get proof state at positionlist_notation_in_statement(state, statement): List the notations in a theoremAll commands return states with feedback containing Rocq messages:
state = client.run(state, "Search nat.")
for level, message in state.feedback:
print(f"Level {level}: {message}")
First install dev dependencies for testing:
uv sync --dev
You can launch all the tests with pytest. The test suite includes tests for both communication modes:
# Run all tests (socket + subprocess modes)
uv run pytest -v .
# Run only socket mode tests
uv run pytest tests/test_unit.py tests/test_integration.py -v
# Run only stdio mode tests
uv run pytest tests/test_stdio.py -v
Note: Socket mode tests require pet-server to be running. Subprocess mode tests require the pet command to be available in PATH.
The complete API documentation is available at: https://llm4rocq.github.io/pytanque
To build the documentation locally:
# Install documentation dependencies
uv sync --extra docs
# Build the documentation
cd docs
uv run sphinx-build -b html . _build/html
# Open the documentation
open _build/html/index.html
We use atdpy to automatically generate serializers/deserializers from protocol type definitions. These types definition should match the ocaml code of petanque in coq-lsp.
To add a new method:
protocol.atdatdpy protocol.atd to generate protocol.pyclient.py with the new methodSocket Mode Connection Errors
pet-server is running: pet-server -p 8765Subprocess Mode Errors
pet command is available in PATH: which petpet binarypet process can access your Rocq/Coq filesFile Path Issues
client.set_workspace()Installation Issues
pet and pet-serverlwt and logs before coq-lsp (required for both modes)pet --version and pet-server --versionPerformance Considerations
Python
100.0%