libreoffice-calc — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited libreoffice-calc (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use the bundled calc modules for UNO-backed Calc spreadsheet work. All paths must be absolute. Bundled modules live under scripts/ in this skill directory, so set PYTHONPATH=<skill_base_dir>/scripts. If setup or runtime issues appear, check references/troubleshooting.md.
# Non-session utilities
create_spreadsheet(path, source=None) # source: path to .json or .xml file to import
export_spreadsheet(path, output_path, export_format) # formats: "pdf", "xlsx", "csv"
snapshot_area(doc_path, output_path, sheet="Sheet1", row=0, col=0, width=None, height=None, dpi=150)
# Session (primary editing API)
CalcSession(path) -> context manager
CalcSession methods:
read_cell(target: CalcTarget) -> dict[str, object]
write_cell(target: CalcTarget, value, value_type="auto")
read_range(target: CalcTarget) -> list[list[dict[str, object]]]
write_range(target: CalcTarget, data)
format_range(target: CalcTarget, formatting: CellFormatting)
list_sheets() -> list[dict[str, object]]
add_sheet(name, index=None)
rename_sheet(target: CalcTarget, new_name)
delete_sheet(target: CalcTarget)
define_named_range(name, target: CalcTarget)
get_named_range(target: CalcTarget) -> dict[str, object]
delete_named_range(target: CalcTarget)
set_validation(target: CalcTarget, rule: ValidationRule)
clear_validation(target: CalcTarget)
create_chart(target: CalcTarget, spec: ChartSpec)
update_chart(target: CalcTarget, spec: ChartSpec)
delete_chart(target: CalcTarget)
recalculate()
patch(patch_text, mode="atomic") -> PatchApplyResult
export(output_path, export_format)
reset()
close(save=True)
# Standalone patch utility
patch(path, patch_text, mode="atomic") -> PatchApplyResultCalcTargetfrom calc import CalcTarget
CalcTarget(
kind="cell" | "range" | "sheet" | "named_range" | "chart",
sheet=None,
sheet_index=None,
row=None,
col=None,
end_row=None,
end_col=None,
name=None,
index=None,
)| Kind | Supported fields | Use |
|---|---|---|
cell | sheet or sheet_index, row, col | Read or write one cell |
range | sheet or sheet_index, row, col, end_row, end_col | Read, write, format, validate, or chart a rectangular range |
sheet | sheet or sheet_index | Rename or delete one sheet |
named_range | name | Inspect or delete one named range |
chart | sheet or sheet_index, plus name or index | Update or delete one chart |
sheet and sheet_index are mutually exclusive.name and index are mutually exclusive.end_row >= row and end_col >= col.read_cell() and read_range() return cell dictionaries with the same shape:
{
"value": 100.0,
"formula": None,
"error": None,
"type": "number",
"raw": 100.0,
}Empty cells return type="empty" with value=None:
{"value": None, "formula": None, "error": None, "type": "empty", "raw": None}Formula cells use type="formula"; when Calc reports a formula error, error is populated and value becomes None.
Boolean values (True/False) are stored as numeric 1.0/0.0. Reading back a cell written with a Python bool returns type="number" with value=1.0 or value=0.0, not a text string.
CellFormattingfrom calc import CellFormatting
CellFormatting(
bold=None,
italic=None,
font_name=None,
font_size=None,
color=None, # named color or integer
number_format=None, # "currency" | "percentage" | "date" | "time"
)Notes:
color accepts a named color or 0xRRGGBB integer.format_range() works for both a cell target and a rectangular range target.ValidationRulefrom calc import ValidationRule
ValidationRule(
type="whole",
condition="between",
value1=1,
value2=10,
show_error=True,
error_message="Enter a value from 1 to 10.",
show_input=True,
input_title="Allowed values",
input_message="Only integers from 1 to 10 are valid.",
ignore_blank=True,
error_style=0,
)Supported type values:
anywholedecimaldatetimetext_lengthlistSupported condition values:
betweennot_betweenequalnot_equalgreater_thanless_thangreater_or_equalless_or_equalChartSpecfrom calc import CalcTarget, ChartSpec
ChartSpec(
chart_type="line",
data_range=CalcTarget(
kind="range",
sheet="Data",
row=0,
col=0,
end_row=5,
end_col=1,
),
anchor_row=7,
anchor_col=0,
width=10000,
height=7000,
title="Revenue Trend",
)Notes:
chart_type must be one of bar, line, pie, or scatter.width and height use Calc chart rectangle units (the same units the packaged API already accepts).Use patch() or session.patch() to apply ordered spreadsheet operations.
[operation]
type = write_range
target.kind = range
target.sheet = Revenue Data
target.row = 0
target.col = 0
target.end_row = 2
target.end_col = 1
data <<JSON
[["Label", "Value"], ["Revenue", 100], ["Cost", 80]]
JSON
[operation]
type = format_range
target.kind = range
target.sheet = Revenue Data
target.row = 1
target.col = 1
target.end_row = 2
target.end_col = 1
format.number_format = currency
format.bold = true
[operation]
type = create_chart
target.kind = sheet
target.sheet = Revenue Data
chart.chart_type = line
chart.data_range.kind = range
chart.data_range.sheet = Revenue Data
chart.data_range.row = 0
chart.data_range.col = 0
chart.data_range.end_row = 2
chart.data_range.end_col = 1
chart.anchor_row = 5
chart.anchor_col = 0
chart.width = 9000
chart.height = 6000
chart.title = Revenue Trendwrite_cellwrite_rangeformat_rangeadd_sheetrename_sheetdelete_sheetdefine_named_rangedelete_named_rangeset_validationclear_validationcreate_chartupdate_chartdelete_chartrecalculatetarget.* fields for the primary target.format.* fields for CellFormatting.rule.* fields for ValidationRule.chart.* fields for ChartSpec; chart source ranges use chart.data_range.*.data must be valid JSON.<<TAG ... TAG for multiline JSON or text.atomic stops on first failure, resets the session, and persists nothing.best_effort keeps successful earlier operations and records failures.PatchApplyResult fields:
modeoverall_status = "ok" | "partial" | "failed"operations = list of PatchOperationResultdocument_persistedFor standalone patch(path, ...), document_persisted means the changes were saved to disk. For session.patch(...), it means the patch produced successful mutations in the current open session state.
from pathlib import Path
from calc import (
CalcSession,
CalcTarget,
CellFormatting,
ChartSpec,
ValidationRule,
)
from calc.core import create_spreadsheet
output = str(Path("test-output/revenue-report.ods").resolve())
create_spreadsheet(output)
with CalcSession(output) as session:
session.rename_sheet(CalcTarget(kind="sheet", sheet="Sheet1"), "Revenue Data")
session.add_sheet("Summary")
session.write_range(
CalcTarget(kind="range", sheet="Revenue Data", row=0, col=0, end_row=2, end_col=1),
[["Label", "Value"], ["Revenue", 100], ["Cost", 80]],
)
session.format_range(
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
CellFormatting(number_format="currency", bold=True),
)
session.define_named_range(
"RevenueValues",
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
)
session.set_validation(
CalcTarget(kind="range", sheet="Revenue Data", row=1, col=1, end_row=2, end_col=1),
ValidationRule(type="whole", condition="greater_than", value1=0),
)
session.create_chart(
CalcTarget(kind="sheet", sheet="Revenue Data"),
ChartSpec(
chart_type="line",
data_range=CalcTarget(
kind="range",
sheet="Revenue Data",
row=0,
col=0,
end_row=2,
end_col=1,
),
anchor_row=5,
anchor_col=0,
width=9000,
height=6000,
title="Revenue Trend",
),
)
session.recalculate()from calc import patch
result = patch(
"/abs/path/revenue-report.ods",
"""
[operation]
type = write_cell
target.kind = cell
target.sheet = Summary
target.row = 1
target.col = 1
value = Ready
value_type = text
[operation]
type = format_range
target.kind = cell
target.sheet = Summary
target.row = 1
target.col = 1
format.bold = true
[operation]
type = recalculate
""",
mode="best_effort",
)
print(result.overall_status)from pathlib import Path
from calc import snapshot_area
result = snapshot_area(doc_path, "/tmp/revenue.png", sheet="Revenue Data", row=0, col=0, dpi=150)
print(result.file_path, result.width, result.height)
Path(result.file_path).unlink(missing_ok=True) # clean up used snapshotsUse snapshots to verify chart placement, formatting, and sheet layout before delivery.
snapshot_area() output dimensions can differ slightly from the requested size; treat small pixel differences as normal.cell and range targets; Calc keeps them distinct even for one-cell selections.create_chart() picks a random later target name; when title is set, targeting the chart by that same name is the safest follow-up pattern.chart.data_range.* fields when patching chart operations.snapshot_area(); Calc export can differ by a small amount.session.close().~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.