Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
"url": "https://github.com/first-tree-ai"
},
"metadata": {
"description": "Install the complete Context Tree plugin for linked, durable project context."
"description": "Install the Context Tree plugin for durable project context."
},
"plugins": [
{
"name": "context-tree",
"description": "Complete Context Tree plugin for linking, reading, and publishing durable project context.",
"description": "Create, connect, read, write, and privately publish durable project context.",
"source": {
"source": "npm",
"package": "@first-tree-ai/context-tree",
Expand Down
4 changes: 2 additions & 2 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "context-tree",
"version": "0.1.5",
"description": "Complete Context Tree plugin with linking, reading, durable writes, and a packaged CLI.",
"version": "0.1.6",
"description": "Durable project context for coding agents: set up, read, write, and privately publish a Context Tree.",
"author": {
"name": "First Tree AI"
},
Expand Down
14 changes: 7 additions & 7 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "context-tree",
"version": "0.1.5",
"description": "Complete Context Tree plugin with linking, reading, durable writes, and a packaged CLI.",
"version": "0.1.6",
"description": "Durable project context for coding agents: set up, read, write, and privately publish a Context Tree.",
"author": {
"name": "First Tree AI",
"url": "https://github.com/first-tree-ai"
Expand All @@ -14,16 +14,16 @@
"hooks": "./hooks/hooks.json",
"interface": {
"displayName": "Context Tree",
"shortDescription": "Resolve and use durable project context",
"longDescription": "Link projects to verified Context Tree checkouts, then resolve, read, and publish durable context without persisting branches or credentials.",
"shortDescription": "Read and write durable project context",
"longDescription": "Set up (create or connect) a verified Context Tree, read the decisions and constraints that bear on a task, record durable decisions, and publish local trees privately.",
"developerName": "First Tree AI",
"category": "Developer Tools",
"capabilities": ["Read", "Write"],
"websiteURL": "https://github.com/first-tree-ai/context-tree",
"defaultPrompt": [
"Link this project to its Context Tree.",
"Read the relevant Context Tree context.",
"Publish this durable decision to the Context Tree."
"Set up a Context Tree (create or connect) when this project has none.",
"Read the relevant Context Tree decisions before changing this code.",
"Write this durable decision to the Context Tree."
]
}
}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ dist/
coverage/
*.tgz
.DS_Store
.context-tree-write.lock
267 changes: 150 additions & 117 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
# Context Tree

`@first-tree-ai/context-tree` gives agents durable project context: decisions,
constraints, and relationships stored as Markdown in a private GitHub
repository. It supports Codex and Claude Code through a portable Agent Plugins
v1 package and includes a CLI for shell automation.
`@first-tree-ai/context-tree` provides durable, structured project context for
coding agents. It ships a portable core, CLI, policy, templates, hook, and six
framework-neutral skills.

Each project is explicitly linked to a verified local checkout. Future sessions
resolve that checkout from the project's credential-free Git origin, or from its
real directory when the project is not a Git repository. Context Tree currently
supports repositories on GitHub.com only; GitHub Enterprise Server and other
forges are not supported.
A Context Tree records current decisions, constraints, relationships, and their
rationale. Source repositories still own implementation detail, task history,
and credentials.

## Install
## Requirements

- Node.js 22.13 or newer
- Git
- GitHub CLI (`gh`) only for connecting a GitHub tree or publishing

Node.js 22.13 or newer and npm are required. Git is also required to initialize
trees and use Git-backed workflows.
Git and GitHub authentication remain owned by the host tools. Repository inputs
are credential-free `OWNER/REPO` identities, never URLs containing credentials.

## Install

### Codex or Claude Code plugin (recommended)

Expand All @@ -35,145 +38,175 @@ claude plugin marketplace add first-tree-ai/context-tree
claude plugin install context-tree@context-tree
```

Marketplace installation requires repository access to
`first-tree-ai/context-tree`. These selectors resolve the npm `latest` package,
which must contain the plugin manifests, hook, four skills and launchers, and
`dist/cli/index.mjs`. Review and trust the session-start hook if your host asks.

The plugin uses its own packaged CLI, so plugin users do not need a global CLI
installation. Try asking:
Both marketplaces install the same npm package, and every plugin component uses
its private packaged CLI rather than a global `PATH` command — so plugin users
need no separate CLI installation. Review and trust the session-start hook if
your host asks. Then try asking:

> Link this project to my Context Tree, then read the relevant context.
> Set up a Context Tree for this project, then read the relevant context.

> Publish this architectural decision to the Context Tree.
> Write this architectural decision to the Context Tree.

### Global CLI (optional)

Install the package globally only when scripts or terminal workflows need a
`context-tree` command on `PATH`:
Install globally only when scripts or terminal workflows need a `context-tree`
command on `PATH`:

```bash
npm install --global @first-tree-ai/context-tree
context-tree --help
```

## CLI workflows
## Six skills

### Setup

`context-tree-setup` orchestrates lifecycle setup for projects with no
connection. It asks whether to create a new tree or connect an existing one,
then delegates to the create or connect workflow rather than duplicating
lifecycle policy. Read and write invoke setup when the current project has no
connection, and the session hook remains silent. Setup never publishes without
explicit confirmation.

### Create

```bash
context-tree create --project-path ./service
```

`create` derives `<normalized-project-directory>-context-tree`, scaffolds and
commits it under `~/.context-tree/trees`, then connects it atomically. It is
idempotent only while the project remains connected to that managed tree.

### Connect

Connect to an existing managed tree by exact name:

```bash
context-tree connect shared-context-tree --project-path ./service
```

Or reuse or clone a GitHub tree by repository identity:

### Initialize or link a tree
```bash
context-tree connect OWNER/REPO --project-path ./service
```

Create a new tree and record a local link for the current project:
Or connect an existing checkout in place by exact disk path:

```bash
context-tree init --repository acme/context --tree-path ./context-tree
context-tree connect --tree-path /path/to/a/tree --project-path ./service
```

Or link a project to an existing, verified checkout:
`connect --tree-path` requires an exact, clean, fully valid Git root with no
symlink components. Trees without an origin connect as local state;
credential-free GitHub origins connect as GitHub state. External disk trees
are never copied, moved, or deleted.

An identical connection is idempotent. An explicit connect automatically
switches the project. GitHub checkouts use the repository's lowercase name in
the same flat managed namespace as created trees.

`context-tree list` reports valid, clean managed trees as
`{ schemaVersion: 1, trees: [{ name, tree }] }`; a missing managed directory
is an empty list.

### Read

```bash
context-tree link --project-path ./service --tree-path ./context-tree
context-tree sync --project-path ./service
context-tree read product/runtime.md --tree-path /path/from/sync
```

If `init` omits `--tree-path`, it creates `./REPO`, using the repository name
verbatim as the directory and tree title. Scaffolding is create-only. It runs
ordinary `git init`, configures a credential-free GitHub origin, and creates a
validation workflow pinned to the package version and selected initial branch.
The init skill, rather than the CLI, owns the initial commit and any publication.
Local trees report their checked-out branch and exact `HEAD` without network
access. GitHub trees perform one fast-forward-only pull of the checked-out
branch. Reads navigate from indexes to narrow, task-relevant children.

### Resolve, refresh, read, and verify
### Write

```bash
context-tree resolve --project-path ./service
context-tree refresh --project-path ./service
context-tree read --tree-path ./context-tree
context-tree read product --tree-path ./context-tree
context-tree verify --tree-path ./context-tree
context-tree prepare-write --project-path ./service
# Edit only the returned worktreePath.
context-tree finish-write --project-path ./service \
--worktree-path /path/from/prepare \
--message "Record runtime constraint"
```

`resolve` checks the recorded checkout, origin, cleanliness, and root
`NODE.md`; it does not scan the whole semantic tree. `refresh` discovers the
live default branch, requires it to match the checked-out branch, and
fast-forwards before reads. Agent reads refresh and fully verify the tree, then
report the exact commit SHA. If GitHub is unavailable, a stale read requires
explicit authorization, is clearly labeled, and can never be used as a write
base.
Preparation synchronizes first and creates a random isolated worktree at that
exact commit. Finishing validates the worktree, stages every pending change,
creates one unsigned commit using the host identity, and attempts one
fast-forward merge for local trees or one non-force push for GitHub trees.

If the destination advanced, `finish-write` returns `WRITE_OUTDATED` and
preserves the worktree. Prepare again and reapply the intended semantic change
once; there is no automatic rebase, retry loop, or pull-request fallback.

Directory reads return the selected `NODE.md` body and metadata plus summaries
of immediate children. Leaf reads return the leaf body without children.
A preserved or abandoned write leaves its temporary worktree on disk and a
`context-tree/write/<name>` branch in the tree. Nothing removes these for you:
clear them with `git worktree remove <path>` and `git branch -D <branch>` in the
connected tree once you no longer need the pending edits.

### Prepare and inspect a write
### Publish

```bash
context-tree stage --project-path ./service
context-tree diff ./prepared-worktree --base HEAD
context-tree publish --project-path ./service
# or: context-tree publish OWNER/REPO --project-path ./service
```

`stage` fetches the live default branch and creates an isolated worktree at its
exact commit. After edits, `diff` reports all pending changes against the given
base (`HEAD` by default). These are preparation and inspection commands: there
is no CLI publish command. The write skill edits, verifies, reviews, commits,
rebases when necessary, and publishes the result.
Publishing requires a clean, valid local tree with no `origin`. It creates one
new private GitHub repository, pushes the checkout, and then changes the stored
connection to GitHub state. Those external and local changes are not atomic;
uncertain or partial outcomes are reported as `PUBLISH_INCOMPLETE` and are not
automatically inspected or repaired.

## Project identity

Git project paths resolve to the exact root of that checkout. A clone or Git
worktree is independent even if it shares an origin or Git common directory.
Non-Git projects match only the exact connected directory; nested directories
do not inherit the connection.

Connection data is written atomically with mode `0600` at
`~/.context-tree/connections.json`. Duplicate project records are corruption.
Stored local/GitHub state is not reclassified from mutable remotes.

Every command that touches a connected tree reports why it refused:
`NO_CONNECTION` (nothing connected), `DIRTY_TREE` (your uncommitted edits —
commit or discard them), `INVALID_TREE` (structure fails `verify`),
`STALE_CONNECTION` (the stored path is gone; connect again), and
`CORRUPT_CONNECTION` (unreadable or duplicated records).

## CLI plumbing

The public command inventory is:

```text
create connect list resolve sync prepare-write finish-write
publish read verify policy
```

Setup, create, connect, read, write, and publish ship as six skills; setup
orchestrates the five concrete workflows. `resolve`, `sync`, `prepare-write`,
`finish-write`, `verify`, and `policy` are plugin plumbing or diagnostic
commands rather than separate user intentions; `list` backs setup's
connect-target discovery.
All machine-readable responses use strict schema version `1`.

`verify` is intended for CI and diagnostics. Normal skills invoke it only after
an operation reports invalid tree content.

### Retrieve the policy
## Development

```bash
context-tree policy
pnpm install
pnpm check
pnpm typecheck
pnpm test
pnpm build
pnpm validate:skills
pnpm check:package
npm pack --dry-run
```

This returns the canonical policy packaged with the installed version.

## Command reference

| Command | Purpose | Essential arguments and options |
| --- | --- | --- |
| `link` | Link a project to a verified checkout | `--project-path <path>`, `--tree-path <path>` |
| `resolve` | Resolve a project's recorded link | `--project-path <path>` (default `.`) |
| `refresh` | Fast-forward a linked tree to its live default branch | `--project-path <path>` (default `.`) |
| `stage` | Prepare an isolated worktree for a write | `--project-path <path>` (default `.`) |
| `diff` | Inspect changes in a prepared worktree | `[tree-path]` (default `.`), `--base <ref>` (default `HEAD`) |
| `init` | Scaffold a new tree | `--repository <owner/repo>`, optional `--tree-path <path>` |
| `policy` | Print the packaged Context Tree policy | None |
| `read` | Read a node or Markdown leaf | `[path]` (default `.`), `--tree-path <path>` (default `.`) |
| `verify` | Validate tree structure and safety | `--tree-path <path>` (default `.`) |

Successful commands and runtime or argument failures emit one
`schemaVersion: 1` JSON object on stdout. Help and version output are plain
text. An invalid `verify` report is still emitted and exits with status 1. The
strict Zod schemas are the source of truth for public wire contracts.

Links are machine-local internal state in
`~/.context-tree/connections.json`; do not edit this file manually. Managed
clones default to `~/.context-tree/checkouts/OWNER/REPO`. Resolution does not
search for moved checkouts, so use the link skill again to repair a stale link.

## Safety and lifecycle

- **Credentials:** The core and CLI neither manage credentials nor perform
authenticated GitHub operations. Repository URLs containing credentials are
rejected and never logged; host Git and GitHub CLI own authentication.
- **Checkout validation:** Linking requires a clean, exact Git root with a safe
GitHub origin and a fully valid tree. Resolution fails closed for symlinks,
moved paths, dirty trees, origin mismatches, and invalid roots. `init` has a
narrow exception for its four new uncommitted scaffold files.
- **Git operations:** Reads fast-forward only. Writes start from a freshly
fetched default-branch commit in an isolated worktree and never force-push.
Commit SHAs identify shared snapshots.
- **Hooks:** Session and subagent hooks inject only a resolved tree identity and
path. They are silent when no link matches and never fetch, clone, or mutate.
They use only the plugin's packaged CLI and warn if it is unavailable.
- **Write fallback:** The write skill retries bounded concurrent updates. If a
direct push is denied or retries are exhausted, it opens a conflict-free PR
from the latest default branch without merging it or requesting reviewers.
Each write and commit is scoped to one concrete source.

For tree structure, link replacement rules, validation boundaries, memory
selection, read/write lifecycle details, and exact public contracts, see the
[Context Tree format specification](docs/specification.md).

## Compatibility

The package uses `.codex-plugin/plugin.json` and `.claude-plugin/plugin.json` as
host adapters for installation and lifecycle integration. It intentionally
omits a root `plugin.json`: Codex 0.151.0 treats that portable manifest as an
alternate plugin shape and fails to discover bundled lifecycle hooks. Both
marketplaces install the same npm package, and all plugin components use its
private packaged CLI at the same version rather than a global `PATH` command.
See [docs/specification.md](docs/specification.md) for contracts and safety
invariants.
6 changes: 3 additions & 3 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ configuration instead of the npm `latest` package:
pnpm test:codex-plugin
```

This opens Codex in a temporary unlinked project. Use
This opens Codex in a temporary unconnected project. Use
`pnpm test:codex-plugin --check` for a non-interactive installation and hook
discovery smoke test. Both modes remove their temporary marketplace, plugin
cache, Codex home, and project when they finish.

Before advertising or releasing the remote marketplace flow, verify that npm
`latest` contains the `.codex-plugin` and `.claude-plugin` current-client
adapters, both marketplaces, `hooks`, all four `skills` and their launchers,
and `dist/cli/index.mjs`. It must not contain a root `plugin.json`, which
adapters, both marketplaces, `hooks`, all six `skills` and their launchers, and
`dist/cli/index.mjs`. It must not contain a root `plugin.json`, which
suppresses bundled-hook discovery in Codex 0.151.0. The package
end-to-end test and `npm pack --dry-run` cover the candidate tarball; checking
`latest` is a release verification step after production publication.
Expand Down
Loading
Loading