Skip to main content

TigerHarness

PyPI Python License

A vendor-agnostic agent harness for Claude Code and OpenAI Codex: iterative task execution, Slack integration, and persistent memory management.

Docs: docs/INDEX.md is the home — it routes you to the right doc in one hop (and separates current reference from design history).

Sub-packages

Package Description
tigerharness.agent_sdk Backend-agnostic agent SDK. Same caller code, swappable runtimes: the claude -p subprocess backend, the codex exec subprocess backend (OpenAI's Codex CLI), and Anthropic's claude-agent-sdk backend, with a shared typed event/retry/error model. Which one a persona runs on is declared per persona in configs/personas.yaml (vendor: claude | chatgpt, with a team default) — see ADR 0011.
tigerharness.journal File-based subscription backend. Routes agent work through the interactive agent app (Claude Code or Codex, per persona) so it counts against a monthly subscription instead of token-billed API. Single-persona tasks (kind=task) and multi-persona workflows (kind=workflow) compiled in-session by a drafter/two-critic loop over mechanical validators, then walked through gates that enforce step order and write persona-stamped worklog notes (the per-persona memory rail). Crash-safe by lease: tasks classify idle/busy/crashed and a fresh session resumes a crashed walk at the same step. Team-pinned scheduling: every task records the journal root it was scheduled into (provenance), scheduling verbs refuse to fall back silently to the per-user journal, and the sweep flags misplaced tasks. A deferred/ inbox makes Slack-side scheduling cheap: journal defer parks the conversation verbatim; journal materialize (inside a drive) turns it into a real task. Drive lanes: every task, workflow step and inbox entry runs on its owner persona's vendor/model — claim refuses other-lane work (exit 3) and step-done prints a handoff: cue (ADR 0012); whether a Slack session may drive at all is a team setting, TIGERHARNESS_JOURNAL_SLACK_DRIVES (ADR 0013). 20 CLI verbs under journal. See docs/journal.md, docs/journal-workflow-mode.md, docs/journal-instant-resume.md.
tigerharness.autodrive Periodic journal driver (the Operator-authorized exception to the human-only drive rule). A detached daemon fires "drive the journal" on a fixed cadence via the backend-agnostic agent_sdk — one drive per vendor/model lane that has work, on that lane's backend (ADR 0012) — fire every N seconds without waiting, so drives may overlap; each fire is a fresh, context-clean session; not built on /loop. Overlap is safe and self-limiting because the journal's busy lease makes a redundant fire a cheap no-op. Before each fire it runs the journal's plain-Python sweep itself, so a busy tick is skipped and an idle tick costs a file walk instead of a model session. Self-driving when opted in (TIGERHARNESS_AUTODRIVE_AUTOSTART in the team's configs/.env): scheduling work starts the daemon, and a drained queue — after the idle memory sweep + context compaction — stops it, so steady state is no process running. Only safe while each vendor CLI (claude -p, codex exec) bills its subscription, so it ships with a --max-budget cap on Claude lanes (Codex has no per-run budget flag; mind the N×-concurrent multiplier), a 60s interval floor, an atomically-locked single-instance-per-team daemon, and an autodrive stop off-switch. See docs/autodrive.md and ADR 0010.
tigerharness.slack_bridge Slack Socket Mode bridge. Forwards DMs to each persona's vendor backend (claude -p or codex exec, resolved from configs/personas.yaml) and posts replies back to the thread. See docs/slack-bridge.md.
tigerharness.tiger_memory Persistent bounded agent memory: three self-pruning stores (skills/must_remember/topics) projected into an index-only session-start briefing, with forgetting via staged compaction (ADR 0007). Includes the team-wide sweep protocol (sweep-plan/sweep-done/sweep-complete/sweep-release under a lease, watermark, and per-wake cap), a lazy team event log (ADR 0008), and subscription-rail staging (plan, ingest-extraction/ingest-staged) so memory extraction bills to the subscription. Sources: Claude Code transcripts (claude_code), Codex session rollouts (codex), Slack threads and journal worklogs; a team sweep can be restricted to one vendor/model lane (sweep-plan --lane-of). See docs/tiger-memory.md, docs/tiger-memory-sweep-protocol.md.

Bundled agent skills (Claude Code + Codex)

tigerharness init installs seven skills into a new team's .claude/skills/ — one vendor-neutral copy that Claude Code reads there and Codex reads through the .agents/skills symlink: drive-journal (the subscription drive loop), journal-new (task/workflow scaffolding), journal-autodrive (start/stop the periodic journal driver), sweep-memory (the team-wide memory sweep), slack-notify (proactive Slack messages), workflow-append-steps (runtime graph extension), and tigerharness-basics (how to operate the team itself: the CLI, the file layout, recruiting personas, creating workflows). Refreshes are hash-aware: a skill that still matches a previously shipped version is updated in place, while a hand-edited skill is left alone (src/tigerharness/init.py).

Installation

Pick the strategy that matches how you want to use tigerharness:

Option A — Scope it to one folder (recommended for teams)

Best when you want a self-contained teams/ directory that owns its own tigerharness install — nothing global, nothing borrowed:

mkdir -p ~/projects/teams && cd ~/projects/teams
uv init --bare                       # creates a minimal pyproject.toml
uv add 'tigerharness[all]'           # adds dep, creates .venv + uv.lock
uv run tigerharness init             # interactive team scaffolder

tigerharness only exists inside this folder's .venv; from then on you invoke it with uv run tigerharness ....

Option B — Install as a global CLI

Best when you want tigerharness available everywhere, like git or gh:

uv tool install 'tigerharness[all]'  # one-time; puts `tigerharness` on PATH
tigerharness init                    # works from any directory

Equivalent with pipx: pipx install 'tigerharness[all]'.

Option C — Traditional pip into an active venv

python -m venv .venv && source .venv/bin/activate
pip install 'tigerharness[all]'
tigerharness init

Choosing extras

tigerharness has zero hard dependencies by design. Optional features are gated behind extras so you don't pay disk/install cost for things you don't use:

Extra Pulls in Enables / required for
(none) init scaffolder, dismiss teardown, the journal subscription backend, autodrive (its Slack notices need [slack]), and the claude_p / codex_exec subprocess backends
[anthropic] claude-agent-sdk The official Claude Agent SDK backend (anthropic_sdk)
[slack] slack-bolt, aiohttp, python-dotenv slack-bridge (Slack Socket Mode DM bridge)
[memory] pyyaml tiger-memory (per-persona persistent memory) and reading configs/personas.yaml for per-persona vendor/model resolution (without it every persona falls back to claude)
[all] union of everything above Everything works out of the box

Pick the union that matches what you'll use, e.g. 'tigerharness[slack,memory,anthropic]' for a Slack-fronted agent with persistent memory and the official SDK backend.

Heads up: the install commands quote the extras ('tigerharness[all]') because zsh treats [ as a glob character. In bash you can drop the quotes, but quoting always works.

Quick start

Scaffold a team and its first persona

tigerharness init is interactive — it walks you through:

  1. Persona name + team (pick an existing team or create one).
  2. Optional toggles: the Slack .env template, multi-team Slack mode (recommended for new setups), and the per-persona memory config.
  3. For a new team: which model vendor it defaults to — Claude (claude -p) or ChatGPT (codex exec) — and an optional default model. Written to configs/personas.yaml; --vendor / --model skip the prompt and --yes takes Claude. Any persona can override with its own vendor: / model: in that file.
  4. The new team's goal (one sentence, seeds the charter's Mission) and the persona's initial traits (recorded in its prompt) — --goal / --traits skip the prompts.
  5. Slack user-ID allowlist for the team's bridge bot (optional).

The memory store is auto-initialized for each new persona with both transcript sources wired in (the Claude Code project path, auto-detected from the team root, and the Codex sessions tree), so the user never has to come back and edit placeholders. Every persona always belongs to a team, and a team is a self-contained directory.

Every team gets two governance folders alongside the runtime config: charter/ holds the team's operating manual (mission, scope, allowed write zones, working conventions, first-read checklist for new personas) and knowledge/ holds the team's curated, lazy-loaded reference base. The generated persona prompt wires both into each persona's first-read flow, so they're load-bearing from day one rather than decorative.

tigers/
├── AGENTS.md                      # vendor-neutral session bootstrap (which persona you are,
│                                  #   where the manual lives, the runtime glossary)
├── CLAUDE.md                      # imports AGENTS.md so Claude Code loads it
├── .gitignore                     # secrets + runtime state (topped up by `init --refresh`)
├── .claude/
│   ├── settings.json             # wires TIGERHARNESS_PERSONAS_CONFIG
│   └── skills/                   # bundled skills (drive-journal, journal-new,
│                                 #   journal-autodrive, slack-notify, sweep-memory,
│                                 #   workflow-append-steps, tigerharness-basics)
├── .agents/
│   └── skills -> ../.claude/skills   # symlink: Codex discovers the same skills
├── configs/
│   ├── personas.yaml              # team registry + default model vendor (auto-updated)
│   ├── repos.yaml                 # path map: team_root + the project the team works on
│   ├── tiger-memory.defaults.yaml # team-wide memory defaults (per-persona configs inherit)
│   ├── slack-bridge.yaml          # this team's bridge lane fragment (multi-team mode)
│   └── .env                       # Slack tokens + team knobs (gitignored)
├── charter/
│   └── README.md                  # team's mission, scope, conventions
│                                  # (single entry point for personas)
├── knowledge/
│   └── README.md                  # curated, lazy-loaded reference base
├── skills/
│   └── README.md                  # drop team-shared skills here
├── personas/
│   ├── chief/
│   │   └── prompt.md              # the persona's system prompt
│   └── scout/
│       └── prompt.md
└── memories/
    ├── chief/
    │   └── tiger-memory.config.yaml   # per-persona memory config
    │                                  #   (claude_code + codex sources)
    └── scout/
        └── tiger-memory.config.yaml

Persona and team names are space-separated words: letters, digits, -, and _, each word starting with a letter or digit, single spaces between words (so chief, scout-7, and Chuan Ying are all valid; leading, trailing, or consecutive spaces are not). Paths printed by init are shell-quoted when a name contains a space.

# Fully interactive — prompts for persona name, team, slack/memory opts
tigerharness init

# Non-interactive — creates team 'tigers' with persona 'chief'
tigerharness init --persona chief --team tigers --yes

# Names may contain single internal spaces
tigerharness init --persona 'Chuan Ying' --team tigers --yes

# Add a second persona to the same team
tigerharness init --persona scout --team tigers --yes

# Skip Slack or memory generation
tigerharness init --persona chief --team tigers --no-memory --no-slack --yes

Tear down a team or persona

tigerharness dismiss is the symmetric counterpart of init — it removes a team (or a single persona inside a team) and all of the associated state: configs, prompts, per-persona memory data, the multi-team index entry, and — for the last team in a multi-team setup — the root's per-root slack-bridge-<root>-<hash> systemd user unit too (discovered by content, so older slack-bridge-multi-* names and the legacy global slack-bridge-multi.service are found as well).

The command is always interactive and gated behind two confirmations (a backup acknowledgement and a type-the-name check), so it's hard to fire by accident:

# Walks you through: pick team-or-persona → preview → backup confirm
# → type the name → execute. Out of scope: deleting the Slack app on
# api.slack.com (the command prints a manual reminder).
tigerharness dismiss

# Same flow but exits after the preview — useful for checking what
# would happen without touching anything.
tigerharness dismiss --dry-run

Refusals are deliberate, not bugs:

  • Dismissing the last persona of a team is refused — use team-level dismissal instead, or add another persona first.
  • Dismissing a persona that's the team's default_persona in the Slack-bridge fragment is refused — pick a new default in the fragment first, then re-run.

Journal (subscription backend)

# 1. Point tigerharness at your team's persona registry
export TIGERHARNESS_PERSONAS_CONFIG=./tigers/configs/personas.yaml

# 2. Scaffold a task for a persona (the drive-journal skill works it)
tigerharness journal new --kind task --persona chief --prd brief.md

# 3. Check the queue
tigerharness journal list

# 4. Sweep state (archives done, classifies in-progress)
tigerharness journal sweep

Slack bridge

One bridge process serves 1..N teams (lanes) — one Slack app per team, separate bot identities, separate threads.json. A single team is just a one-lane index.

# 1. Fill in each team's Slack tokens in <team>/configs/.env (from api.slack.com)
#    SLACK_APP_TOKEN=xapp-...  SLACK_BOT_TOKEN=xoxb-...  SLACK_ALLOWED_USER_IDS=U0123ABC
# 2. Create a lanes index listing your team(s):
printf 'lanes:\n  - tigers\n' > slack-bridge.yaml
# 3. Point the bridge at it and run:
export TIGERHARNESS_BRIDGES_CONFIG=$PWD/slack-bridge.yaml
python -m tigerharness.slack_bridge

tigerharness init auto-registers each new team's lane. TIGERHARNESS_BRIDGES_CONFIG is required: the former single-tenant fallback was removed on 2026-08-11 (ADR 0009), and the bridge now fails fast at startup with a migration pointer when it is unset. See docs/slack-bridge.md for the full setup and migrating off single-tenant.

Tiger memory

Each persona has its own memory config under tigers/memories/<persona>/tiger-memory.config.yaml. init fills in both transcript sources (the Claude Code project path detected from the team root, and the Codex sessions tree), so it works as-is; to also ingest the persona's journal work, add a journal_worklog source (see docs/per-persona-journal-memory.md). Then:

--config is a top-level option for the tiger-memory sub-command, so it must appear before the verb:

# Save typing — the same path is reused everywhere
CFG=tigers/memories/chief/tiger-memory.config.yaml

# 1. Initialize the memory store (per persona)
tigerharness tiger-memory --config $CFG init

# 2. Rebuild the session-start briefing (no model call; the in-session
#    `sweep-memory` skill does the actual extraction)
tigerharness tiger-memory --config $CFG rebuild

# 3. Search memory
tigerharness tiger-memory --config $CFG search "solar energy"

# 4. Pin a must-memorize fact
tigerharness tiger-memory --config $CFG pin "Prefers solar over wind"

Configuration

All paths are resolved from environment variables -- no hardcoded paths. "Where" says which file a variable belongs in: the team configs/.env (per-team, read by the bridge lane, the journal and autodrive; never pollutes the process env), the bridge process env (multi-bridge.env via systemd EnvironmentFile=), or the session / process env of whatever CLI or agent session is running.

Variable Where Default Description
TIGERHARNESS_BRIDGES_CONFIG bridge process env (none; required for the bridge) Path to the slack-bridge.yaml lanes index (see docs/slack-bridge.md)
TIGERHARNESS_PERSONAS_CONFIG .claude/settings.json (written by init) or session env (none) Path to the team's configs/personas.yaml for journal verbs run inside a session
SLACK_ALLOWED_USER_IDS team configs/.env (none) Comma-separated Slack user IDs the bridge answers; the notify CLI's DM target
SLACK_NOTIFY_CHANNEL team configs/.env (none → operator DM) Ops-log channel for proactive notifies, turn-progress heartbeats and autodrive notices (invite the bot to it)
TIGERHARNESS_JOURNAL_SLACK_DRIVES team configs/.env unset (off) 1 lets a Slack-triggered session journal claim (drive) without --allow-api-drive; off means Slack schedules, never drives (ADR 0013)
TIGERHARNESS_AUTODRIVE_AUTOSTART team configs/.env unset (off) 1 makes scheduling start the autodrive daemon and a drained queue stop it (ADR 0010)
TIGERHARNESS_AUTODRIVE_INTERVAL team configs/.env 600 Seconds between daemon fires (floor 60)
TIGERHARNESS_AUTODRIVE_MAX_BUDGET team configs/.env (none = uncapped) USD cap handed to each drive's backend
TIGERHARNESS_AUTODRIVE_DRIVER team configs/.env the team's default persona --driver persona for daemon drives; its vendor/model is the daemon's home lane
TIGERHARNESS_AUTODRIVE_NOTIFY, TIGERHARNESS_AUTODRIVE_NOTIFY_CHANNEL team configs/.env slack; channel falls back to SLACK_NOTIFY_CHANNEL, then the operator DM slack or none: daemon heartbeats + threaded drive summaries; the channel value dm pins them to the operator DM (see docs/autodrive-notifications.md)
TIGERHARNESS_SLACK_ENV notify CLI process env (none) Explicit .env path for the notify CLI's credential lookup and the turn-progress heartbeats' env fallback
TIGERHARNESS_ATTACHMENT_DIR bridge process env /tmp/slack-attachments Where to stage downloaded files
TIGER_MEMORY_CONFIG session / process env (none) Path to tiger-memory YAML config
TIGER_MEMORY_CLI team configs/.env (none → tiger-memory on PATH) tiger-memory CLI binary for the bridge's post-thread rebuild
TIGERHARNESS_JOURNAL_DIR session / process env the team root's journal/ when the cwd is a team dir, else $XDG_STATE_HOME/tigerharness-journal (~/.local/state/…) Overrides the journal root (autodrive sets it for the drives it launches)
TIGERHARNESS_JOURNAL_STUCK_TIMEOUT session / process env 1800 (30 min) Heartbeat age (seconds) past which the journal sweep treats an attached in_progress task as crashed (below it, busy)
TIGERHARNESS_LOG_LEVEL session / process env WARNING (notify: INFO) Log level for every tigerharness CLI and daemon

Examples

See examples/ for a fully-populated sample team folder (examples/tigers/) and standalone reference configs:

Requirements

  • Python 3.11+
  • For the default claude_p backend: the Claude Code CLI (claude) on PATH.
  • For the codex_exec backend (personas with vendor: chatgpt): the Codex CLI (codex) on PATH, signed in with codex login.
  • For the anthropic_sdk backend: install with [anthropic] extra; pulls in claude-agent-sdk.

Known limitations & roadmap

Gaps we've hit in real use, tracked here so they can be picked up later. None of these block normal use once the listed workaround is applied.

Bridge boot environment

  • claude not found on PATH when the bridge auto-starts at boot. On distros where the Claude Code CLI is installed outside /usr/bin (e.g. NixOS at /run/current-system/sw/bin/, npm-global at ~/.npm-global/bin/, pipx at ~/.local/bin/), the systemd unit emitted by tigerharness slack-bridge gen-service has no Environment=PATH=... line. Restarting from an interactive shell works (the rich PATH is inherited from the live user session), but a cold boot auto-start sees only the minimal systemd PATH (/usr/bin:/bin), so shutil.which("claude") in the SDK fails with backend error: \claude` not found on PATH`.
    • Workaround: a systemd drop-in at ~/.config/systemd/user/<your-bridge-unit>.service.d/path.conf (e.g. slack-bridge-teams-4a8c8b.service.d/) containing [Service]\nEnvironment="PATH=/run/current-system/sw/bin:/usr/bin:/bin" (adapted to the local install location). Drop-ins survive gen-service regeneration.
    • Fix candidates: (a) gen-service emits a sensible default Environment=PATH= covering common install locations; (b) add a CLAUDE_CLI env var the bridge reads and forwards as cli= to ClaudePBackend(), mirroring the existing TIGER_MEMORY_CLI knob.
    • Same shape for codex (personas on vendor: chatgpt): the Codex CLI's standalone install lands in ~/.local/bin, which the drop-in must also list.
  • Same shape applies to the tiger-memory binary used by the bridge's post-thread rebuild trigger. The existing TIGER_MEMORY_CLI env var already provides the per-team-.env workaround, but a PATH default in gen-service would fix both at once.

Bridge setup ergonomics

  • gen-service references multi-bridge.env but doesn't create it. The generated systemd unit has EnvironmentFile=<teams-root>/multi-bridge.env, and the bridge won't start without that file existing (systemd skips a missing optional EnvironmentFile silently, but the bridge then fails because $TIGERHARNESS_BRIDGES_CONFIG is unset). The user has to manually echo "TIGERHARNESS_BRIDGES_CONFIG=/path/to/slack-bridge.yaml" > <teams-root>/multi-bridge.env as a separate step after gen-service. Fix candidate: have gen-service either emit the env file alongside the unit (skipping if it already exists), or at least print a clear "you must now create this file with the following contents" hint.

  • Two .env files with non-obvious, very different semantics. In multi-team mode there are two distinct env files:

    • multi-bridge.env (referenced by systemd EnvironmentFile=): loaded into the bridge process's os.environ. Used only for the bootstrap pointer TIGERHARNESS_BRIDGES_CONFIG. Adding other env vars here does not reach per-lane behavior, because the per-team loader reads from disk into a separate dict.
    • per-team configs/.env (referenced by the YAML index's per-lane env: key): loaded via _load_env_file into a per-lane dict that deliberately does not pollute os.environ. This is where Slack tokens, TIGER_MEMORY_CLI, SLACK_NOTIFY_CHANNEL, TIGERHARNESS_PERSONAS_CONFIG, and any agent-facing env vars go.

    The Configuration table above carries a "where it goes" column for exactly this reason.

Bridge shutdown

  • The drain budget has only ever been exercised with one turn in flight. On shutdown the bridge waits up to _DRAIN_TIMEOUT_S for its in-flight turns to finish, and that wait is released by a single self._drained.set() that fires when the in-flight counter reaches zero. The counter can only exceed 1 with concurrent dispatches, which no test creates — so the "still in flight, do not release yet" side of that check has never run, and it sits behind a # pragma: no branch that keeps the 100% coverage gate green over it. The margins in the budget chain (STOP_DRAIN_S + FINISH_POST_S <= _DRAIN_TIMEOUT_S <= TimeoutStopSec) exist precisely for the multi-turn case, so the case they were sized for is the one with no coverage. See "The drain budget is a chain, not a number" for the full ordering and the reasoning behind each margin.
    • Fix candidate: a test with two concurrent dispatches in which the first to finish must not set _drained. That reaches the untested branch and lets the pragma come off.
    • Why it isn't already written — so this doesn't read as neglect. The gap was found and documented by a documentation step, and the pragma predates that branch, so writing a new test there would have shipped unreviewed new behaviour from a docs seat. The reason it is recorded rather than closed is a scope boundary, not an oversight or a difficulty. The test is small; whoever picks it up should expect it to be.
    • The branch is unexercised, not unreachable — this matters if you are cleaning up pragmas. The standing rule at a 100% branch floor is to delete a branch the design made unreachable rather than pragma over it. That rule does not apply here: concurrent dispatches genuinely reach the "still in flight" side, no test creates them. Delete the pragma once the test above exists; do not delete the branch.
    • Not known to misbehave — this is an untested path, not a reported bug.

Agent Slack notifications

  • Notifications require the bot to be in SLACK_NOTIFY_CHANNEL. Each team has its own Slack app (own bot user). After creating a new team's Slack app and setting SLACK_NOTIFY_CHANNEL in configs/.env, the bot must be invited to that channel (/invite @BotName in Slack). Without this, chat.postMessage returns channel_not_found and notifications are silently skipped. The notify CLI logs the error to stderr but doesn't surface it to the user.
    • Fix candidate: tigerharness init could print a reminder ("Don't forget to invite your bot to the ops-log channel"), or the notifier could log a more prominent first-time warning.
    • This now also covers autodrive, which inherits SLACK_NOTIFY_CHANNEL as the last layer of its notify-channel chain. A team that set the key but never invited the bot can decline the inheritance with TIGERHARNESS_AUTODRIVE_NOTIFY_CHANNEL=dm and keep its daemon heartbeats in the operator DM. See autodrive.md.
  • Agents need .claude/settings.json + skills to send proactive DMs. Agents use the slack-notify skill to send per-iteration updates via python -m tigerharness.slack_bridge.notify. Without .claude/settings.json (which wires TIGERHARNESS_PERSONAS_CONFIG) and .claude/skills/slack-notify/SKILL.md (which teaches the agent the notify CLI exists), the agent doesn't know how to send Slack messages. As of v0.2.1+, tigerharness init scaffolds these automatically for new teams. Existing teams adopt them with tigerharness init --refresh, which installs any missing skills, refreshes un-customized ones to the latest, recreates the .agents/skills symlink if missing, and tops up .gitignore with any newly-shipped rule — without clobbering hand edits.
  • --thread must be passed when notifying from a Slack thread. When an agent sends a proactive message from a Slack DM thread, it must pass --thread <slack_thread_ts> (from the [bridge-context] block) so notifications land in the right thread. Without it, notifications go to a new top-level message instead of the conversation thread. The slack-notify skill documents this prominently, but it's easy to forget.

tigerharness init

  • Auto-init of the tiger-memory store fails intermittently with CalledProcessError during tigerharness init's last step. Running tigerharness tiger-memory --config <path> init by hand afterward always succeeds, suggesting environment propagation in the sys.executable -m tigerharness ... subprocess is the moving part. A direct in-process call would remove it.

License

MIT

Release files for TigerHarness 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for TigerHarness 0.6.1
File Size Uploaded
tigerharness-0.6.1.tar.gz 1.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for TigerHarness 0.6.1
File Interpreter ABI Platform
tigerharness-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.8 MB

Release files / tigerharness-0.6.1.tar.gz

Download URL tigerharness-0.6.1.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
343e945c2633f2012b3c0dbea078c10b4c75d64ca0e42520e474e503528a8f27
BLAKE2b-256 checksum
How to use checksums
6f742c9ac77bdac320fdbef361474b48a2dd31bfad4d50fc0275e57b0e8a4c48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / tigerharness-0.6.1-py3-none-any.whl

Download URL tigerharness-0.6.1-py3-none-any.whl
Size 601.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fdcc8d5d08074259d6a64144a895faef876167b0c131c77a5186a4e48e020a69
BLAKE2b-256 checksum
How to use checksums
a0f0242609bd47c63cbfa951e63da20122d0e5c7cccc091f5af591a4c6e6f39c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page