callumalpass44 downloadsLocal-first, file-based agent inbox for typed requests and responses.
Pickle is a local-first, file-based Obsidian inbox for typed agent requests and structured human responses.
It turns a plain Markdown folder into a lightweight Pickle Inbox:
_pickle/requests/_pickle/responses/Pickle is for human checkpoints in local automation. It is useful when an agent or scheduled job needs a real decision before it changes state, posts a comment, closes an issue, deploys something, or applies a generated plan.
The important idea is that request state is represented as files, not as ephemeral UI state. A request is answered when a response file links back to it. Downstream automation should consume the response file, copy the decision into its own workflow state, and leave the Pickle files intact.
_pickle collection layout.pickle_request, pickle_response_approval, and pickle_response_ack
type files.Pickle Requests.base file with request and response views.status.Pickle works fine as a standalone Obsidian plugin, but can also be used with these related projects:
_pickle schema.1.12.2 or newer.Pickle keeps the mdbase.yaml and _types/ files so agents can share the same
schema contract, but the plugin itself reads and writes through Obsidian's vault
API. It does not need Node or a filesystem-backed vault at runtime.
By default the plugin maintains this folder in the vault:
_pickle/
mdbase.yaml
Pickle Requests.base
_types/
pickle_request.md
pickle_response_approval.md
pickle_response_ack.md
requests/
responses/
attachments/
The folder names can be changed in plugin settings.
Agents create request files with type pickle_request:
---
type: pickle_request
title: "Approve issue close-out?"
source: "tasknotes-ops"
kind: approval
priority: normal
response_type: pickle_response_approval
message: "Please approve, reject, or revise this proposed close-out."
created_at: "2026-05-24T00:00:00.000Z"
dedupe_key: "tasknotes-closeout-1234"
attachment_paths:
- "attachments/tasknotes-closeout-1234/context.md"
context:
cwd: "/home/calluma/projects/tasknotes"
repo: "callumalpass/tasknotes"
task: "close issue 1234"
---
Please approve, reject, or revise this proposed close-out.
Key fields:
title: human-readable request title.source: creator or automation source.message: short request text for clients that consume frontmatter directly.kind: request shape, such as approval, choice, input, notice, or
message.priority: low, normal, high, or urgent.status: legacy lifecycle marker. It may be used for cancelled, but it is
not authoritative for answered state.response_type: name of the response type file the modal should render.dedupe_key: stable key for repeated automation checks.attachment_paths: collection-relative paths to supporting files.context: small structured metadata for the request pane.Large logs and long context should usually be attachments instead of frontmatter.
The default response type is pickle_response_approval:
---
type: pickle_response_approval
request: "[[requests/approve-issue-close-out]]"
decision: approve
comment: "Looks good."
responded_at: "2026-05-24T00:05:00.000Z"
responder: human
---
Do not infer approval from the request body or request status alone. A request is
answered when a response file links back to it through request.
Message requests can use the bundled pickle_response_ack type:
---
type: pickle_response_ack
request: "[[requests/read-update]]"
message: "Acknowledged."
responded_at: "2026-05-24T00:05:00.000Z"
responder: human
---
A request can point at any response type in _pickle/_types/ by setting
response_type.
For example, a richer response schema can ask for booleans, repeatable steps, and nested review metadata:
---
name: pickle_response_complex
description: Complex approval response.
display_name_key: decision
fields:
request:
type: link
target: pickle_request
validate_exists: true
required: true
decision:
type: enum
values: [approve, reject, revise]
required: true
risk_accepted:
type: boolean
required: true
rollout_steps:
type: list
items:
type: string
min_items: 2
review:
type: object
fields:
summary:
type: string
required: true
severity:
type: enum
values: [low, medium, high]
comment:
type: string
---
The modal renders editable fields recursively:
Generated, computed, and system-managed fields such as id, request,
responded_at, responder, and attachment_paths are written by the plugin and
are not shown as user-editable fields.
Pickle: Maintain collection, or let the plugin create the collection on
load.Pickle: Open request base.Pending view.The default base file includes these views:
PendingAnsweredConflictsAll requestsResponsesApprovedRejectedRevisionsCommands appear under the Pickle: prefix in Obsidian:
Maintain collection: create or refresh folders, type files, and the base file.Validate collection: validate Pickle files against the local type files.Open request base: open the maintained base file.Respond to current request: open the response modal for the active request
file.Collection folder: default _pickle.Requests folder: default requests.Responses folder: default responses.Attachments folder: default attachments.Base file: default Pickle Requests.base.Default responder: default human.The sibling skill in ../pickle-obsidian-skill describes the agent-facing
workflow. In short:
_pickle/requests/.response_type exists under _pickle/_types/._pickle/attachments/<request-id>/.mdbase validate from inside _pickle when available.request link targets the request.response_type.Keep rejection and revision handling explicit in the upstream workflow. Pickle is the request inbox and audit trail, not the owner of every downstream state machine.
Install dependencies:
npm install
Run checks:
npm run typecheck
npm run lint
npm test
npm test includes a compatibility harness that imports selected core fixtures
from ../mdbase-spec/tests when that sibling repo is present. To run only those
imported mdbase-spec cases:
npm run test:mdbase-spec
Build the plugin:
npm run build
Build and copy into the configured test vault:
npm run build:test
copy-files.mjs copies main.js, styles.css, and manifest.json. By default
it copies to:
/home/calluma/testvault/test/.obsidian/plugins/pickle
Set OBSIDIAN_PLUGIN_PATH or create .copy-files.local to copy elsewhere.
After copying, reload in Obsidian:
obsidian plugin:reload id=pickle
obsidian dev:errors limit=20
The build workflow runs linting, typechecking, tests, a production build, release metadata checks, and GitHub artifact attestations for the Obsidian install assets. It uploads these assets as a workflow artifact:
main.jsmanifest.jsonstyles.cssTo publish a GitHub release for Obsidian, update manifest.json,
package.json, versions.json, and CHANGELOG.md, then push a tag that exactly
matches the manifest version:
git tag 0.1.0
git push origin 0.1.0
The workflow publishes or updates the matching GitHub Release with the three
plugin assets. Use plain semver tags such as 0.1.0; do not prefix release tags
with v.