metadata.type="transcript" tag and the
application/x-ndjson content type without adding a transcript resource, endpoint, or
server-side schema. Start with the checked-in
recommended NDJSON example,
or store your agent’s existing transcript format.
Use one session for the transcript and its outputs
Give the transcript and every artifact produced during a run the same session ID. You can then list the whole run or filter it to the transcript alone.--transcript defaults the upload to content_type=application/x-ndjson and adds
metadata.type=transcript. It does not change output, errors, TTL, sealing, deduplication,
idempotency, or upload limits.
Explicit values take precedence
Write precedence is independent for the two defaults:- An explicit content type always wins; otherwise a true transcript flag supplies
application/x-ndjsonbefore filename MIME guessing. - The presence of an explicit metadata
typekey always wins, includingtype=""; otherwise a true transcript flag suppliestype="transcript". - When the flag is omitted or false, existing MIME guessing and metadata behavior remain unchanged.
type filter wins, including an empty value. Otherwise
a true transcript flag adds exactly one metadata.type=transcript filter. Other metadata is
preserved in every case.
Python SDK
transcript is a keyword-only boolean on the existing push() and list() methods. Their
public signatures are:
content plus filename form:
MCP tools
Both the TypeScript and Python MCP servers expose the same optional boolean on the existing tools.store_artifact remains a writeIdempotent tool, and list_artifacts remains a
safe tool.
store_artifact arguments
list_artifacts arguments
content_type and metadata.type; list calls preserve an
explicit metadata.type filter.
Call the REST API directly
The REST API is unchanged. API-direct callers express the convention with existingmetadata, content_type, and metadata-filter parameters. The API does not infer NDJSON
from metadata.type alone, so send the desired content type explicitly.
Multipart upload
Multipart metadata is a JSON string.file and content_type are separate existing form
fields.
JSON-body upload
JSON uploads carry base64 content,content_encoding="base64", a filename, object
metadata, and an explicit content type.
List transcripts
Use the existing metadata query and URL-encode the query string:Capture Claude Code sessions automatically
This recipe uses Claude Code’s client-sideSessionEnd hook to invoke the same Artifacta
CLI push shown above. Artifacta does not run a listener or provide a separate capture
service.
Prerequisites
- Install and authenticate the
artifactaCLI, and ensureartifactais onPATH. - Install
jqand ensure it is onPATH. - The documented hook expects JSON on stdin with
session_id,transcript_path, andreason. It reads the first two fields;transcript_pathmust name an existing file.
~/.claude/settings.json:
~/.claude/hooks/push-transcript.sh with these exact contents:
jq to fail. Missing, null, or empty required fields and a nonexistent
transcript file also fail validation. Any non-zero Artifacta CLI exit propagates as a
non-zero Claude Code hook failure. Input validation and the Artifacta push still fail hard:
there are no retries and no swallowed push errors. Model extraction alone is best-effort; if
it fails or finds no main-loop model, the script pushes the transcript without model metadata
rather than losing the upload.
Model capture
The hook script above also records which model produced the session, straight from the transcript itself:metadata.model— the last main-loop assistant model in the transcript. Sidechain (subagent) entries and synthetic placeholders are excluded via the transcript’sisSidechainmarker, so a session that dispatched subagents on a different model still attributes to the orchestrating model — the model that directed the work and decided what got stored.metadata.model_source=transcript— marks the value as machine-captured. Absence ofmodel_sourcemeans the model was declared by the caller.metadata.models_used— every distinct model observed in the transcript, comma-separated (e.g.claude-fable-5,claude-sonnet-5), including subagent sidechains.
models_used is “models observed”, never exhaustive.
For pushes outside the hook, declare the model yourself: artifacta push report.pdf --model claude-fable-5 (shorthand for --meta model=), or export
ARTIFACTA_MODEL once in a wrapper script — explicit flags always beat the
environment. If a wholly-delegated subagent authored the artifact, pass that
subagent’s model explicitly.
Published pages render metadata.model in the page receipt automatically.
Verify a captured transcript
transcript.
For a later native Claude Code lifecycle check, use the repository’s
reproducible SessionEnd operator validation.
That optional follow-up is not a PR blocker: automated exact-hook tests and live execution
with canonical synthetic stdin already passed.
Security: audit before you push
Artifacta does not automatically scan, redact, or block secrets in transcript uploads. Callers are responsible for reviewing and redacting transcript content before storage. For an optional source-checkout audit, run the repository’s existing scanner against a directory before pushing it:0 when clean, 1 when it finds credential-shaped content, and 2 for
a usage error. It reports locations and pattern names without echoing matched values. The
repeatable --allow <string> option can suppress a known benign match. This user-run audit
is optional, is available only from a source checkout, and is not an Artifacta push gate;
you may wire it into your own pre-push hook if desired.
Codex plugin
Artifacta plugin1.1.0 supports verified transcript capture in Codex. Install and
authenticate it with the Codex plugin guide, then start a new
thread so Codex loads the plugin’s skills and hooks.
For an immediate snapshot, ask:
“Use Artifacta to capture this Codex session’s transcript.”The
capture-transcript skill searches Codex’s rollout files for a distinctive phrase from
the current conversation and refuses to continue unless it identifies exactly one regular
file. It copies that live rollout to a private snapshot, uploads the snapshot through
Artifacta MCP store_artifact, and removes the private copy after a successful upload.
Codex transcript capture never invokes the local Artifacta CLI or sends a local filesystem
path to the hosted MCP server.
For one capture at the current thread’s next Stop, include the explicit flag:
“Use Artifacta to capture this Codex session’s transcript —automatic.”
--automatic arms one unredacted snapshot for this thread only. It does not enable
every-turn capture, future-thread capture, or a background uploader. Open /hooks, review
the bundled Artifacta hook, and trust its current definition; Codex skips untrusted
non-managed hooks.
An immediate mid-turn snapshot may not include the request that triggered capture or the
assistant response reporting its result. Retrieve captured records with list_artifacts
using the returned session ID and transcript=true.
Limitations and hard exclusions
- Transcript payloads remain opaque bytes. NDJSON is recommended, not a mandatory schema.
- There is no incremental, streaming, chunked, or per-turn upload/reassembly behavior.
- There are no dedicated
push_transcript,get_transcript,pull-transcript, or MCPget_transcriptAPIs or tools. - There is no server-side agent-session detection or continuous capture mechanism. The Claude Code and Codex plugin skills perform verified client-side capture.
- There is no server-side enforcement of the
metadata.typeconvention and no transcript web viewer. - Existing artifact limits, retention/TTL choices, session seals, and errors apply unchanged.