Agent skill

Rust Ffi

by ariebovenberg in ariebovenberg/whenever

Instructions for using whenever's internal Rust FFI abstractions

MITAuto-check passedDevelopment

Install Rust Ffi

skills CLI
$ npx skills add ariebovenberg/whenever --skill rust-ffi -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install ariebovenberg/whenever rust-ffi --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/ariebovenberg/whenever.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/rust-ffi .claude/skills/rust-ffi && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
rust-ffi
GitHub stars
2.4k
Token cost
~2.5k tokens
SKILL.md length
1,045 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
MIT

At a glance

Instructions for using whenever's internal Rust FFI abstractions

  • Tasks that involve Type safety
  • SKILL.md covers FFI approach: pyo3_ffi, not pyo3, Module State pattern, Method registration and Performance philosophy, plus 3 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Rust Ffi is an agent skill from ariebovenberg/whenever. Instructions for using whenever's internal Rust FFI abstractions

Its SKILL.md is about 2.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Type safety. It works with Rust and Python. The repository describes itself as: ⏰ Type-safe datetimes for Python that get DST right. Rust or pure Python, your choice. The licence is MIT.

When your agent uses it

  • Tasks that involve Type safety

Example prompts

  • “Use the rust-ffi skill to instruction for using whenever's internal Rust FFI abstractions”
  • “/rust-ffi”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit 0e51a9c. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are rust).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Rust Ffi loads about 2.5k tokens when it runs. Until then it costs about 18 tokens; SKILL.md has 1,045 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~18
When it runs · the whole SKILL.md, loaded when a task matches
~2.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from ariebovenberg/whenever at commit 0e51a9c, republished under its MIT licence (© ariebovenberg). 1,045 words, ~2,493 tokens.

Download SKILL.mdSave it as .claude/skills/rust-ffi/SKILL.md (or your agent's skills folder).
name
rust-ffi
description
Instructions for using whenever's internal Rust FFI abstractions

Rust FFI Instructions

FFI approach: pyo3_ffi, not pyo3

The low-level pyo3_ffi module is used, not pyo3 directly. This avoids overhead, complex abstractions, and gives full control over generated code. The src/py/ module provides safe wrappers. Key types:

TypePurpose
PyObjCore wrapper around *mut PyObject. Has .extract() (Copy types), .extract_ref() (ref types), .type_(), .is_none()
Owned<T>RAII refcount wrapper. Use Owned::new() to take ownership, .borrow() for non-owning access
PyClass<T>A Python class whose instances contain a Rust T; carries module state via .state() → &State
PyRef<'a, T>A borrowed extension instance together with access to its T payload
PyPayloadTrait implemented by Rust values stored inside extension objects
PyTypeA Python type object
PyReturnAlias for PyResult<Owned<PyObj>> — the return type of Python-visible functions
PyErrMarkerSentinel indicating the Python error indicator is set

Key helpers in src/py/:

  • raise_value_err(), raise_type_err(), raise_key_err() — raise Python exceptions
  • warn_with_class(cls, msg, stacklevel) — emit a Python warning. Takes PyObj, not a raw pointer
  • handle_kwargs(fname, kwargs, handler) — iterate kwargs with interned string matching
  • handle_no_args(fname, args) — reject positional arguments
  • handle_one_arg(fname, args) — extract exactly one positional arg, or raise TypeError
  • handle_opt_arg(fname, args) — extract zero or one positional arg
  • handle_one_kwarg(fname, key, kwargs) — extract a single optional kwarg by key
  • raise_mixed_args(fname), raise_unexpected_kwarg(fname, key) — keep common argument errors consistent in class-specific parsers
  • obj.expect_int(name) — accept a Python int or subclass and raise TypeError: {name} must be an integer otherwise
  • find_interned(value, &[(string, value), ...]) — match a PyObj against an interned-string/value table, returning Option
  • match_interned_str(name, value, &[(string, value), ...]) — like find_interned but raises on no match
  • find_interned_with(value, handler) — compose multiple interned-string matchers while retaining one global pointer-equality pass before Unicode comparison
  • find_interned_by(value, choices, eq) — match one table using the equality function supplied by find_interned_with
  • match_type!(obj, type => |value| {...}, _ => {...}) — match an extension object against differently typed PyClass<T> values; prefix an arm with ref for non-Copy types
  • CompareOp::from_ffi(op).apply(a, b) — apply a CPython rich-comparison operation to ordered Rust values
  • generic_alloc(cls, data) — allocate a Python object with the given payload
  • PyAsciiStrBuilder::format() — build a Python string without intermediate Rust String
  • PyTuple::with_len() / unsafe .init_item_unchecked() — allocate and initialize tuple slots
  • .to_py() via the ToPy trait — convert Rust values to Python objects
  • .to_tuple() — convert a Python sequence to a tuple (prefer over seq_len+seq_getitem)
  • import(module_name) — import a Python module (don't call PyImport_ImportModule directly)

Module State pattern

State (in src/pymodule/def.rs) is a large struct stored on the Python module. It holds:

  • HeapType<T> for each class (date_type, time_delta_type, etc.)
  • Exception classes (exc_repeated, exc_skipped, etc.)
  • Warning classes (warn_deprecation, warn_days_not_always_24h, etc.)
  • Interned strings (str_years, str_hour, str_units, etc.)
  • Unpickling functions

Access it via cls.state() from any PyClass<T>.

Method registration

Methods are registered in a static mut METHODS: &[PyMethodDef] array using macros:

  • method0! — no args
  • method1! — one positional arg
  • method_vararg! — variable positional args
  • method_kwargs! — positional args + keyword args
  • classmethod1!, classmethod_kwargs! — class methods

The function signatures must match the macro used. For method_kwargs!:

rust
fn my_method(cls: PyClass<MyType>, slf: MyType, args: &[PyObj], kwargs: &mut IterKwargs) -> PyReturn

Performance philosophy

  • Avoid unnecessary allocations. Use helpers to build Python objects directly (e.g., PyAsciiStrBuilder instead of format!() → to_py())
  • Prefer i32/i64 over i128 when possible
  • Use tuples (not lists) for immutable Python sequences
  • For known strings, check pointer equality before falling back to direct Unicode comparison

Common patterns

Positional argument handling:

rust
// No positional args:
handle_no_args("method_name", args)?;
// Exactly one required arg:
let arg = handle_one_arg("method_name", args)?;
// Zero or one optional arg:
let maybe_arg = handle_opt_arg("method_name", args)?;

Kwarg handling:

rust
handle_kwargs("method_name", kwargs, |key, value, eq| {
    if eq(key, str_some_kwarg) {
        // parse value
    } else {
        return Ok(false); // unrecognized kwarg
    }
    Ok(true)
})

Single optional kwarg shortcut:

rust
let relative_to = handle_one_kwarg("total", state.str_relative_to, kwargs)?;

Building deltas from kwargs (shift/add/subtract methods): Use common::shift_args::parse_datetime_shift_kwargs() for full datetime units or parse_calendar_shift_kwargs() for calendar-only units. They return a typed DateTimeShift or CalendarShift; the datetime parser's callback retains class-specific kwargs such as disambiguate and warning suppression. For a positional delta, use parse_datetime_shift_arg() or parse_calendar_shift_arg(); these raise the method-specific type error if the argument is not a supported delta.

Instant-like arguments: Use common::instant::extract_instant() when a non-Instant operand should fall through to another operation, and parse_instant_arg() for a required Instant, OffsetDateTime, or ZonedDateTime argument. Both normalize to the domain Instant.

Interned string matching with custom errors: Use find_interned + manual error message when you need a specific error format. Use match_interned_str when the default error format is acceptable. For composed subsets, use find_interned_with(value, |v, eq| ...), call find_interned_by(v, choices, eq) for table-shaped subsets, and use eq(v, expected) for individual strings. Do not call top-level find_interned separately for each subset: that would perform Unicode comparison before later subsets have had their pointer-equality pass.

Error handling:

  • raise_value_err("msg")? for ValueError
  • .ok_or_value_err("msg")? on Options — for domain errors with specific messages
  • .ok_or_range_err()? on Options — for generic out-of-range errors (preferred)
  • PyErrMarker() (with parens) as the sentinel in PyResult<T>
Show full SKILL.md (345 more words)Show less

Type-specific gotchas

  • ZonedDateTime doesn't implement Ord in Rust. Compare via .to_instant() for ordering. Non-Copy (contains Arc<TimeZone>). Uses Arc::ptr_eq + content equality for timezone comparison. DST-aware operations resolve PlainDateTime::local_seconds() through TimeZone::mapping_for_local() and PlainDateTime::resolve_in().
  • LocalSeconds is the local-wall-time coordinate; don't pass EpochSecs to local timezone lookup. LocalMapping, Disambiguation, and ResolvePolicy define gap/fold handling in the domain layer. Map ResolveError to Python exceptions only in binding code.
  • OffsetDateTime compares by instant (Instant has Ord). Offset is an Offset scalar.
  • Use PlainDateTime::assume_offset() when attaching a validated offset and assume_offset_unchecked() only when the represented instant is already known to be in range.
  • PlainDateTime compares by local date+time. Has Ord.
  • Shift arguments use CalendarShift and DateTimeShift in the domain layer. Prefer Date::shift_by() and PlainDateTime::shift_by() once a shift has been parsed. Python-facing component replacement starts with PlainDateTime::components() and uses DateTimeComponents in classes::plain_datetime.
  • TimeDelta stores secs: DeltaSeconds + subsec: SubSecNanos. Use .total_nanos() -> i128. Has .in_single_unit() and .in_exact_units() for unit decomposition, and owns the pure parse_iso() implementation; map its parse errors to Python exceptions in the binding.
  • Unit types name their role: fmt::Precision, round::RoundUnit, and CalendarUnit/DifferenceUnit/ExactUnit in domain::difference. Keep these domains distinct unless their parsing and behavior are demonstrably identical. Keep common::fmt free of Python argument parsing; common::format_args adapts Python format_iso arguments to its pure types.
  • ItemizedDelta/ItemizedDateDelta use DeltaField<T> with the integer type's MIN value as the UNSET sentinel. DeltaField has custom Debug showing <unset> for sentinel values and .as_option() for checked extraction.

Development philosophy

  • Avoid new macros when the logic isn't complex enough to warrant them. Slightly repetitive code is preferred over macro abstractions that obscure intent.
  • Move logic into domain types: put computation methods on the data type itself rather than in free functions. This keeps FFI glue thin.
  • Use .ok_or_range_err() for out-of-range errors instead of custom messages.
  • Use // SAFETY: comments for unsafe blocks per the Rust convention (exact casing matters).
  • Don't downcast integer types without an explicit check or comment explaining why it's safe.
  • pub(crate) not pub for internal visibility.
  • Leverage the type system for safety: use distinct types to make invalid states unrepresentable. Prefer validated newtypes over raw primitives for constrained values.

© ariebovenberg, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/rust-ffi of ariebovenberg/whenever.

Open the folder on GitHubat commit 0e51a9c

Compare with similar skills

Rust Ffi next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Rust Ffi compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Rust Ffi this skillariebovenberg/whenever2.4k—~2.5kAutomated safety check: PassMIT
Strict Programming Practicescode-yeongyu/oh-my-openagent70k—~9.5kAutomated safety check: PassCustom licence
Minimizing Ty Ecosystem Changesastral-sh/ruff50k—~4.6kAutomated safety check: PassMIT
RTK Rust Design Patternsrtk-ai/rtk83k—~1.9kAutomated safety check: PassApache-2.0
Kedro Babysitkedro-org/kedro11k—~4kAutomated safety check: PassCustom licence
Dignified Python Standardsdocling-project/docling69k—~1.5kAutomated safety check: PassApache-2.0

Similar skills

  • Strict Programming Practices

    code-yeongyu/oh-my-openagent

    Applies strict, type-first coding rules for Python, Rust, TypeScript and Go, loading the matching language reference before the agent writes or edits any code.

    70k GitHub stars~9.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Official

    A skill your agent uses when a user says "minimize this ty ecosystem change", "reproduce this ecosystem result", "investigate a primer difference", "investigate a mypyprimer difference"…

    50k GitHub stars~4.6k tokensUpdated today
    DevelopmentAuto-check passed
  • Describes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill.

    83k GitHub stars~1.9k tokensUpdated today
    DevelopmentAuto-check passed
  • Kedro Babysit

    kedro-org/kedro

    Run Kedro's local lint / format / type-check / tests on changed files (uses the project's pre-commit hooks, ruff, mypy, pytest, lint-imports, detect-secrets, Make targets — in the right venv), or…

    11k GitHub stars~4k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Dignified Python Standards

    docling-project/docling

    Applies opinionated production Python conventions chosen by the project's Python version: modern type syntax, pathlib, explicit checks and interface guidance.

    69k GitHub stars~1.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Release Skills

    nexmoe/eve

    Universal release workflow. An agent skill from nexmoe/eve.

    421 GitHub starsUsed in 3 repos~3.3k tokens
    DevelopmentAuto-check passed

Works with

Categories

Questions about Rust Ffi

What does Rust Ffi do?

Instructions for using whenever's internal Rust FFI abstractions. Rust Ffi is an agent skill from ariebovenberg/whenever.

When should I use Rust Ffi?

Rust Ffi fits situations like: tasks that involve Type safety.

How do I install Rust Ffi in Claude Code?

Run `npx skills add ariebovenberg/whenever --skill rust-ffi -a claude-code`. Or copy the skill folder (.agents/skills/rust-ffi in ariebovenberg/whenever) into .claude/skills/rust-ffi in your project. Claude Code loads it when a task matches its description.

How do I install Rust Ffi in Codex?

Run `npx skills add ariebovenberg/whenever --skill rust-ffi -a codex`. Or copy the skill folder (.agents/skills/rust-ffi in ariebovenberg/whenever) into .agents/skills/rust-ffi in your project. Codex loads it when a task matches its description.

Can I use Rust Ffi in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ariebovenberg/whenever --skill rust-ffi -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rust-ffi, .gemini/skills/rust-ffi, .github/skills/rust-ffi and .opencode/skills/rust-ffi in your project.

What does Rust Ffi need to run?

SKILL.md names no scripts, command-line tools or credentials: Rust Ffi is instructions for the agent only. Our summary lists: Python 3.

Does Rust Ffi access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Rust Ffi safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Rust Ffi use?

Rust Ffi is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Rust Ffi use?

About 2.5k tokens (SKILL.md is roughly 10k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Rust Ffi?

Skills that share tags, products or a category with Rust Ffi: Strict Programming Practices (code-yeongyu/oh-my-openagent, 70k stars), Minimizing Ty Ecosystem Changes (astral-sh/ruff, 50k stars), RTK Rust Design Patterns (rtk-ai/rtk, 83k stars) and Kedro Babysit (kedro-org/kedro, 11k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Rust Ffi?

ariebovenberg (a GitHub user) maintains it in ariebovenberg/whenever, which has 2,407 GitHub stars. The repository was last updated on October 9, 2026.

Source: ariebovenberg/whenever on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.