kythe is a small, dependency-free client for scripts and terminals. It is the human counterpart to the MCP surface your instances use.
Install
Download the archive for your platform from github.com/kythene/cli/releases (linux / macOS / Windows, amd64 / arm64), extract the kythe binary and put it on your PATH. On macOS/Linux:
tar xzf kythe_*_$(uname -s | tr A-Z a-z)_*.tar.gz kythe
sudo mv kythe /usr/local/bin/
kythe --helpWith source access you can also build it from a checkout: go build -o kythe .
Configure
export KYTHENE_URL=https://kythene.com # default; your own host if self-hosting
export KYTHENE_TOKEN=twk_... # an API key (create one in the app)KYTHENE_TOKEN takes a twk_ API key (recommended). Create keys in the app under Connect your AI / Settings; copy at creation (shown once).
A key acts as your own account. Same access as you (the default) carries exactly your permissions in a workspace and nothing more, and follows your current role - if that changes, or you leave the workspace, the key's access changes with it. Narrow a key at creation to Read-only (recall and reads) or Write-only (publishing from apps and crons). Choose the workspace scope too: this workspace only, or all of yours.
Commands
This reference documents kythe v0.12.0. Run kythe --version to check the build you have; if it is older, some flags below may not yet be present.
kythe create-collection <file>... [--tag T]... [--title X] [--space S]
kythe ingest --body TEXT [--kind K] [--severity S] [--title X] [--tag T]... [--producer P] [--space S]
kythe version <collection-id> <file>... [--note X] [--space S]
kythe timeline [QUERY] [--tag T] [--limit N] [--json] [--space S] (QUERY, or --search Q)
kythe get <collection-id> [--json] [--space S]
kythe artifact <artifact-id> [--content] [--version N] [--out FILE] [--json] [--space S]
kythe archive <collection-id> [--restore] [--space S]
kythe add <collection-id> <file>... [--ref <artifact-id>]... [--note X] [--space S]
kythe reorder <collection-id> <artifact-id>... [--space S]
kythe move <artifact-id> <from-collection-id> <to-collection-id> [--space S]
kythe delete <collection-id> [--undelete] [--space S]
kythe wikis [QUERY] [--json] [--space S] the wikis in this workspace
kythe pages <wiki> [--json] [--space S] its pages, as a tree
kythe page <wiki> [page-path] [--json] [--space S] the page's markdown, on stdout
kythe create-wiki <name> [--slug S] [--description X] [--approval] [--body B] [--space S]
kythe create-page <wiki> <title> [--parent P] [--slug S] [--file F|-] [--body B] [--space S]
kythe update-page <wiki> [page-path] (--file F|- | --body B) [--title X] [--note N] [--base N] [--space S]
kythe page-state <wiki> [page-path] <state> [--note N] [--reviewer R] [--space S]
kythe move-page <wiki> <page-path> [--parent P] [--slug S] [--space S]
kythe remember <file|-> [--title X] [--project P] [--type T] [--tag T]... [--alias A]... [--private] [--supersedes ID] [--space S]
kythe recall [QUERY] [--project P] [--type T] [--scope everything|memory] [--include-deprecated] [--limit N] [--json] [--space S]
(QUERY, or --search Q)
kythe catchup [--peek] [--limit N] what changed since this instance last looked
kythe forget <memory-id> [--space S]
kythe deprecate <memory-id> [--replaced-by ID] [--restore] [--space S]
kythe link <from-memory-id> <to-memory-id> [--space S]
kythe unlink <from-memory-id> <to-memory-id> [--space S]
kythe promote <memory-id> <target-space> [--space S]
kythe review <collection-id> --artifact ID (--block <anchor|"text"> | --annotation <id>) --status STATUS [--comment X] [--space S]
kythe set-review <collection-id> [on|off] [--space S]
kythe share <collection-id> <target-space> [--space S]
kythe unshare <collection-id> <target-space> [--space S]
kythe share-code <tag> --label X [--expires-days N] [--pin NNNN] [--space S]
kythe share-codes [--tag T] [--space S]
kythe revoke-code <share-code-id> [--space S]
kythe share-pin <share-code-id> <pin> [--space S] (or --clear to remove a PIN)
kythe unlock-code <share-code-id> [--space S]
kythe projects [QUERY] [--space S] (QUERY, or --search Q)
kythe tag delete <name-or-id> [--space S]
kythe tag merge <source>... --into <target> [--space S]
kythe tag rename <name-or-id> <new-name> [--space S]
kythe tag password <name-or-id> <password> [--space S] (or --clear to remove)
kythe spaces
kythe create-space <name>
kythe space-slug <slug> [--space S]
kythe export [--out DIR | --archive FILE] [--space S]
kythe import --archive FILE [--into SPACE] [--dry-run]Throughout, the --space / <target-space> arguments name a workspace - "space" is the CLI's name for a workspace (see About --space below). Omit --space when you belong to just one.
Every command takes a global --token twk_... that overrides KYTHENE_TOKEN for that call - handy for a one-line cron with a scoped write-only key.
timeline, get, recall and artifact take --json, emitting the structured data behind the command (stable field names) instead of the human-readable text - for scripting. Without it the output is unchanged.
review - flag one block of a renderable artifact (and optionally comment).
--blockis a block anchor or a verbatim snippet;--statusis one ofneeds_review,needs_work,done,approved,reject_remove(empty clears). Use--annotation <id>instead of--blockto act on a thread whose block was rewritten so its anchor no longer resolves (the id comes fromkythe get). Only when the collection has requested review.set-review - turn the approval/review flow on or off for an existing collection, without re-publishing it.
publish - publish one or more files as a new collection. Repeat
--tagfor several tags; a tag can name a project or set access. A published markdown file renders[[Title]]wikilinks to a sibling document, a collection or a memory; an unresolved one stays plain text.ingest - publish a lightweight event/alert from a machine producer (a health check, a cron, a CI job) with no file:
--bodybecomes a text artifact and--kind/--severitybecome tags. Pair it with a write-only--token.version - add a new version of artifact(s) to an existing collection; bumps its revision.
--noterecords why.add - add files to an existing collection instead of republishing (which would create a new collection and abandon its comments and history). Pass new files by path, and/or reference already-published files of the same workspace with
--ref <artifact-id>; they append and bump the revision. If the collection is shared by a code, a warning names the holders who gain read access.reorder - set the order of a collection's files. List every current file id, once, in the order you want (get them from
kythe get); a partial or unknown-id list is rejected. Comments and reviews stay attached to their files.move - move one file from one collection to another in the same workspace, carrying its comments, reviews and history. It appends to the destination; if the move empties the source, the source archives itself. A warning names any share-code holders who gain read access. Cross-workspace moves are refused - use
sharefor that.timeline - the collection feed, newest first; filter by
--tagor search.get - show a collection and its artifacts by id.
artifact - show an artifact's version history;
--contentfetches one version's bytes (--version N,0= latest) to--out FILEor stdout.archive - archive a collection: a reversible retirement that hides it from the timeline, recall and search until you restore it (
--restore). Nothing is deleted and no storage is freed - it stays viewable and restorable by id.delete - schedule an archived collection for permanent deletion. It stays recoverable for 30 days (
--undeleteto cancel), then its content, files and history are erased for good, in every workspace it was shared into. Archive it first -deletefails on a live collection.remember - store a memory (from a file or stdin
-).--projectscopes it; re-remembering the same--titlein the same--projectsupersedes it, and--supersedes IDreplaces a named memory whatever its title (the way to heal a near-miss fork, since the new version can carry the corrected title).--typesets the note's kind (decision, how-to, gotcha, reference, person, meeting - free text);--tagsays what it is about.--aliasadds extra names a[[wikilink]]can reach it by, and--privatestores it author-private.[[wikilinks]]in the body link to other memories (by title, title-slug, alias or case-insensitively). A title is derived from the body's first line when--titleis omitted (a leading markdown#is stripped).recall - return the most relevant context with its full artifact content in one call. By default it spans everything you can access - memory and published work (each result tagged
memoryorcollection);--scope memorynarrows to memory only. Filter by--project,--typeand--search, and cap the count with--limit N(default 25, max 100).--include-deprecatedalso returns memories flagged stale, each with what replaced it - hidden by default so instances stop applying them, but there when you are auditing what the team used to believe. Each result prints its memory id (whatforget/deprecate/link/promotetake) and its provenance -by youfor your own, otherwiseby <author>, with· via <instance>. Recall blends full-text and semantic matching, and also returns the workspace guide.deprecate - mark a memory stale so recall stops surfacing it (
--restoreto un-deprecate;--replaced-byto point at its replacement).link / unlink - curate an explicit link between two memories, on top of the
[[wikilinks]]parsed from bodies.promote - promote a memory into another workspace you belong to, held for review there until an owner approves.
forget - permanently remove a memory by id (prefer
deprecatewhen the knowledge is superseded rather than wrong).share / unshare - map a collection into another workspace you belong to (or remove that mapping); the origin is untouched.
share-code / share-codes / revoke-code - mint a share code for a tag (a private link for an outsider -
--labelrecords who it is for), list the codes, and revoke one.--expires-days Ntime-boxes a code;--pin NNNNadds a second-factor PIN so the link alone (forwarded, screenshotted) is not access - it reaches a PIN prompt instead.share-codesmarks codes that carry a PIN and any that are locked out. Internal tags cannot have share codes.share-pin / unlock-code -
share-pin <id> <pin>sets or changes a code's PIN without changing the link (so a rotation does not invalidate what you sent);share-pin <id> --clearremoves it.unlock-code <id>clears a PIN brute-force lockout (a code locks after a few wrong attempts). See Sharing and guests.projects - list the projects (project-kind tags) in the workspace - the valid
--projectvalues forremember/recall.tag delete / merge / rename / password - manage the tag taxonomy and access.
deleteremoves a tag (untagging its collections and revoking its share codes);mergere-tags every source's collections onto--into <target>then removes the sources (one command to fold many stray projects into one);renamechanges a tag's name;password <tag> <pw>(or--clear) sets the tag's anonymous-view password. The server refuses an internal tag and a private project that still holds collections (removing its gate would expose them).export / import - export a whole workspace to a directory (
--out) or a.tar.gz(--archive), and import one back (into an empty--intoworkspace). Your data is yours - plain markdown + files, no lock-in. Owner/admin token.spaces - list the workspaces you belong to (with each one's slug); the current one is marked.
space-slug - set this workspace's readable slug, the segment in its anonymous share links (
/v/<slug>/<tag>/...). Stable across a rename; the id-based form keeps working, so links already sent stay valid.
About --space
--space selects the workspace (what the flag calls a "space" - the tenant). Pass an id or a name from kythe spaces. Omit it when you belong to one workspace. --project (on remember/recall) scopes to a project within the workspace.
Examples
# publish a benchmark into the 'api' project
kythe create-collection ./bench.json --tag api --title "Nightly bench"
# add a newer run to the same collection
kythe version 28f7adc5-... ./bench.json --note "after the index change"
# stash and recall a project memory
kythe remember runbook.md --project acme --title "Deploy runbook"
kythe recall --project acme
# target a specific workspace by name
kythe timeline --space "Acme workspace"Exit codes
0 success, 1 a runtime/API error (message on stderr), 2 a usage error.
Working with a wiki
A wiki is addressed by its slug (or id); a page by its path within that wiki - the same path the contents list shows you. The wiki's home page has no path, so leave the argument off to mean it:
kythe page estate # the home page
kythe page estate hardware # a page within it
kythe page-state estate published # publish the home page
kythe page-state estate hardware published # publish that pagekythe wikis # slug, id, name, published/total
kythe pages handbook # the tree, with drafts marked
kythe page handbook onboarding/day-one # the markdown, on stdoutkythe page writes the page body to stdout and everything else to stderr, so it redirects and diffs cleanly:
kythe page handbook onboarding/day-one > day-one.md
kythe page handbook onboarding/day-one | diff - day-one.mdWriting a page:
kythe create-page handbook "Day one" --file ./day-one.md
kythe page-state handbook day-one publishedA new page is a draft - your team can see it, nobody else can - until you publish it. update-page reads the page's current revision itself, so a second writer cannot silently overwrite the first:
kythe update-page handbook day-one --file ./day-one.md --note "added the parking bit"
kythe page-state handbook day-one publishedPushing a directory of markdown in:
for f in docs/*.md; do
kythe create-page handbook "$(basename "$f" .md)" --file "$f"
done