{"id":50559646,"url":"https://github.com/technicalpickles/petri-dish","last_synced_at":"2026-06-04T11:01:14.738Z","repository":{"id":360997172,"uuid":"1251689600","full_name":"technicalpickles/petri-dish","owner":"technicalpickles","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-28T19:31:20.000Z","size":123,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-28T20:15:43.013Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/technicalpickles.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T20:30:20.000Z","updated_at":"2026-05-28T19:31:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/technicalpickles/petri-dish","commit_stats":null,"previous_names":["technicalpickles/petri-dish"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/technicalpickles/petri-dish","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fpetri-dish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fpetri-dish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fpetri-dish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fpetri-dish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/technicalpickles","download_url":"https://codeload.github.com/technicalpickles/petri-dish/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fpetri-dish/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33901305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-04T11:01:13.780Z","updated_at":"2026-06-04T11:01:14.720Z","avatar_url":"https://github.com/technicalpickles.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# petri-dish\n\nA petri-dish for agentic coding experiments. Keep your cultures in your lab; load them into a dish to see how they grow.\n\n## Why\n\nYour `~/.claude/` is production. There's no staging copy of it, no rollback if a hook misbehaves or a plugin clobbers your settings. [I've written about this.](https://pickles.dev/dot-claude-is-production/) `CLAUDE_CONFIG_DIR` gets you a sandbox; petri-dish gets you reproducible experiments inside one.\n\nA **culture** is one experiment: a `config.yml` + `prompt.md` pair. A **petri-dish** is what runs it. Each dish is isolated via [cenv](https://github.com/technicalpickles/cenv) so the experiment never touches your real config, and hooks injected into the dish observe the run from inside without disturbing it.\n\n## What it does\n\n`petri-dish run \u003cculture\u003e` boots an isolated cenv environment, injects PreToolUse/PostToolUse/PermissionRequest hooks, runs Claude Code against your prompt, and correlates the event log into a structured results file.\n\n## Requirements\n\n- Ruby \u003e= 3.2\n- [cenv](https://github.com/technicalpickles/cenv) for environment isolation\n- tmux\n- The Claude Code CLI (`claude`)\n\n## Install\n\n```\ngem install agent-petri-dish\n```\n\nThat puts `petri-dish` on your PATH. (The gem name is prefixed because `petri_dish` was already taken on rubygems; the CLI stays `petri-dish`.)\n\n### Without setting up Ruby\n\nIf you don't want to deal with a Ruby toolchain, use [rv](https://github.com/spinel-coop/rv). It manages an isolated Ruby per tool and installs one for you if you don't have one.\n\n```\nbrew install rv\nrv tool install agent-petri-dish\n```\n\nFor one-off invocation without touching shell init:\n\n```\nrv tool run --from agent-petri-dish petri-dish list\n```\n\nFor the `petri-dish` binary on your PATH, follow `rv shell \u003cyour-shell\u003e` to wire rv into your shell.\n\n### From source\n\n```\ngit clone https://github.com/technicalpickles/petri-dish.git\ncd petri-dish\ngem build petri-dish.gemspec\ngem install agent-petri-dish-0.1.0.gem\n```\n\n## Quick start\n\n```\nmkdir my-lab \u0026\u0026 cd my-lab\nmkdir -p cultures/my-first-culture\n# write cultures/my-first-culture/config.yml and prompt.md\npetri-dish setup my-first-culture\npetri-dish run my-first-culture\npetri-dish results my-first-culture\n```\n\nBy default, petri-dish looks for cultures in `./cultures/` relative to your current directory. Override with `--cultures-dir \u003cpath\u003e` or `PETRIDISH_CULTURES_DIR`.\n\nTo explore the bundled examples, from the cloned petri-dish repo:\n\n```\npetri-dish run --cultures-dir examples sandbox-01-baseline\n```\n\n## How it works\n\n1. **Environment.** Each culture gets its own cenv environment with specific settings (sandbox config, permissions, plugins). Nothing touches your `~/.claude/`.\n2. **Hooks.** PreToolUse, PostToolUse, and PermissionRequest hooks are injected into the dish to log events and auto-handle permission prompts.\n3. **Prompt.** A markdown prompt tells Claude what commands to run and what to observe.\n4. **Results.** Hook event logs are correlated into structured results (prompted vs silent, timing, outcomes).\n\n## CLI reference\n\n```\nUsage: petri-dish \u003ccommand\u003e [options]\n\nCommands:\n  run \u003cculture\u003e [--deny] [--debug] [--keep] [--cultures-dir DIR]\n  list                    List available cultures\n  results [culture]       Show past results\n  setup [culture]         Create environments\n  setup --clean [culture] Tear down environments\n  help                    Show this help\n```\n\n## Adding a culture\n\nEach culture directory needs two files:\n\n```\ncultures/my-culture/\n  config.yml\n  prompt.md\n```\n\nSee `examples/` for working configs. The schema:\n\n```yaml\nname: my-culture\ndescription: \"One-line description\"\n\nenvironment:\n  name: test-my-culture\n  plugins: []\n  settings:\n    sandbox:\n      enabled: true\n    permissions:\n      allow:\n        - Read\n        - Write\n\nruntime:\n  work_dir: /tmp/sandbox-test\n  preamble: lib/preambles/sandbox.md   # optional, resolves to a bundled or local preamble\n  inject_results_file: true\n  timeout: 300\n\nprompt_mode: accept   # or \"deny\"\n```\n\nFor a longer reference, including prompt-shape conventions, cell discipline (baseline cells, multi-run averaging, A/B variants), preamble selection, and the brittle bits to watch for, see [`claude-plugin/skills/petri-dish/references/authoring-cultures.md`](claude-plugin/skills/petri-dish/references/authoring-cultures.md).\n\nIf you use Claude Code, the [companion plugin](claude-plugin/README.md) ships that same reference as a skill so an agent can author cultures with the discipline already in working memory.\n\n## Examples included\n\n- `sandbox-*`: probes of Claude Code's sandbox behavior across filesystem, network, IPC, and escape-hatch settings.\n- `permissions-*`: how permission prompts behave under different settings.\n- `guidance-*`: prompt-layer interventions for sandbox-safe path selection.\n- `parser-*`: Claude Code's permission parser boundary cases.\n\n## License\n\nMIT. See LICENSE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnicalpickles%2Fpetri-dish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechnicalpickles%2Fpetri-dish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnicalpickles%2Fpetri-dish/lists"}