diff --git a/.github/workflows/trust.yml b/.github/workflows/trust.yml index 648c4bc..3d1cf63 100644 --- a/.github/workflows/trust.yml +++ b/.github/workflows/trust.yml @@ -25,6 +25,12 @@ jobs: - name: Install dependencies run: bun install --frozen-lockfile + - name: Install hi (Human Intent) + run: cargo install human-intent --version 0.5.0 --locked + + - name: Human Intent check + run: hi check + - name: CorvidLabs Trust gate id: trust uses: CorvidLabs/trust@fcc889f54d8b4892a81af463c5a0250e2be66fc5 # v1.2.0 diff --git a/.gitignore b/.gitignore index 5c2179d..e555722 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ augur.json # spec-sync 5.x auto-fix backups .specsync/backup-fix/ + +# human-intent rendered page +intent.html diff --git a/INTENT.md b/INTENT.md new file mode 100644 index 0000000..981ad1e --- /dev/null +++ b/INTENT.md @@ -0,0 +1,18 @@ +# let + +Every coding agent hides its assets in a private layout, so a Grok session cannot see Claude's worktrees and a Claude session cannot route Cursor's skills. `let` should be the one boring, host-neutral answer to what agent stuff is here and where am I, federating what already exists on disk instead of creating another silo to migrate into. It should feel like a locator rather than a platform: fast, read-only by default, honest about what it cannot see, and stingy with context so agents pull what they need instead of being handed everything. It reads a machine full of transcripts and credentials, so the thing it must never do is leak them. + +## Features + + +- [find](hi/find.md): FIND (21 criteria) +- [fleet](hi/fleet.md): FLEET (20 criteria) +- [guard](hi/guard.md): GUARD (13 criteria) +- [history](hi/history.md): HISTORY (10 criteria) +- [hosts](hi/hosts.md): HOSTS (14 criteria) +- [orient](hi/orient.md): ORIENT (14 criteria) +- [route](hi/route.md): ROUTE (10 criteria) +- [show](hi/show.md): SHOW (18 criteria) +- [wire](hi/wire.md): WIRE (17 criteria) +- [workbed](hi/workbed.md): WORKBED (19 criteria) + diff --git a/hi/find.md b/hi/find.md new file mode 100644 index 0000000..0ad37cd --- /dev/null +++ b/hi/find.md @@ -0,0 +1,34 @@ +--- +hi: 1 +families: [FIND] +--- + +# Finding agent assets + +## Intent + +The whole product starts here: one command that answers what agent stuff exists for this project, across every coding agent installed on the machine. Assets stay where their host put them, so finding is a read over what already exists rather than a migration into somewhere new. Worktrees are the hardest case, because git and several agents all have an opinion about the same folder, and the answer has to be one entry per checkout. Searching should be cheap enough to run reflexively, and safe enough to run in a repository that has never heard of this tool. + +## Criteria + +- **FIND-1** I can ask which worktrees exist for the project I'm standing in, whichever agent made them. + - **FIND-1.a** A checkout that both git and an agent's own folder know about appears once, not twice. + - **FIND-1.b** A worktree keeps the same identity even when let changes its mind about which agent owns it. + - **FIND-1.c** A worktree folder an agent made but git hasn't registered yet still shows up. + - **FIND-1.d** A folder that only looks like a checkout is listed without claiming a branch for it. +- **FIND-2** The same command finds every kind of agent thing, so I never have to learn a different command per kind. + - **FIND-2.a** Asking for a kind that nothing on this machine provides gives me an empty list rather than an error. +- **FIND-3** I can limit a search to a single agent when that's all I care about. +- **FIND-4** I can narrow a search with a few words, matching names, descriptions and trigger phrases. +- **FIND-5** By default I get what belongs to the project I'm standing in. +- **FIND-6** I can deliberately widen a search to everything on this machine. +- **FIND-7** Asking what skills I have here includes the ones installed globally, because that is what the question means. +- **FIND-8** A long result is trimmed to a size I can actually read. + - **FIND-8.a** I can raise or lower that trim for a single search. + - **FIND-8.b** No search returns more than a fixed ceiling, however large a number I ask for. +- **FIND-9** A trimmed result still tells me how many things there really were. +- **FIND-10** Results arrive nearest first, so what belongs to this project sits above what merely exists on the machine. +- **FIND-11** Two skills that share a name but come from different agents both stay in the list. +- **FIND-12** Every result tells me where the thing actually lives, so I can go and open it myself. +- **FIND-13** A search comes back fast enough that I'd run it before every task instead of guessing. +- **FIND-14** Searching never changes anything on disk. diff --git a/hi/fleet.md b/hi/fleet.md new file mode 100644 index 0000000..83e87a6 --- /dev/null +++ b/hi/fleet.md @@ -0,0 +1,33 @@ +--- +hi: 1 +families: [FLEET] +--- + +# Watching the fleet + +## Intent + +A local page that answers what my agents are doing right now: which are working, in which project and worktree, and on what. It should be built from what let already indexed plus a look at which agent processes are really running, so working now means a live process and never a warm timestamp. It watches and nothing more, so no button on the page starts, stops or steers anything. Nothing secret-shaped should reach the browser, and anything let can't work out should be labelled unavailable rather than guessed at. + +## Criteria + +- **FLEET-1** I can start a local page that shows what my agents are doing. +- **FLEET-2** The page is reachable only from this machine. + - **FLEET-2.a** I can put it on a different port. + - **FLEET-2.b** A port that isn't a real port is refused before anything starts listening. +- **FLEET-3** Agents come first and projects second, because I'm usually asking about an agent. +- **FLEET-4** An agent shown as working now really has a process running. +- **FLEET-5** An old session is never dressed up as a live agent. +- **FLEET-6** Each working agent shows where it's working: which project, which worktree, which branch. +- **FLEET-7** An agent that can't be matched to a project is shown as unassigned rather than hidden. +- **FLEET-8** I can expand an agent to see what it was last asked to do. +- **FLEET-9** I can see a recent slice of an agent's output without going and opening its files myself. +- **FLEET-10** Anything shaped like a token, a password or a local path is masked before it reaches the page. +- **FLEET-11** Detail let can't get is labelled unavailable rather than guessed at. +- **FLEET-12** No button on the page can start, stop or steer anything. +- **FLEET-13** The page keeps itself up to date without me reloading. + - **FLEET-13.a** A refresh doesn't lose the panel I had open or where I'd scrolled. +- **FLEET-14** When an agent starts working or first appears, a screen reader is told about it. + - **FLEET-14.a** An announcement never steals the focus I was using. +- **FLEET-15** I can see whether the worktree an agent is in has uncommitted work. +- **FLEET-16** Every list on the page is capped so a busy machine still renders. diff --git a/hi/guard.md b/hi/guard.md new file mode 100644 index 0000000..5750f89 --- /dev/null +++ b/hi/guard.md @@ -0,0 +1,26 @@ +--- +hi: 1 +families: [GUARD] +--- + +# Keeping private things private + +## Intent + +let reads a machine full of chat transcripts, credential files and other people's projects, so the most important thing about it is what it refuses to do. Transcripts should be known by their existence and never by their contents, and files that usually hold secrets should be listed by path and never opened. Scanning should stay inside a known set of folders so it can't be aimed at an arbitrary tree. A repository I just cloned should never be able to talk let into reading more or running more than it already could. + +## Criteria + +- **GUARD-1** Finding, showing or opening a chat transcript gives me its size and age, never its contents. +- **GUARD-2** A file that usually carries credentials is known by its path alone and never opened. +- **GUARD-3** A settings file that can embed keys or environment values is indexed by its path and never read out. +- **GUARD-4** Standing in one project, I'm not handed the sessions and memory of every other project on this machine. +- **GUARD-5** A repository's own let settings can't grant it more reach than it already has. + - **GUARD-5.a** A repository can still choose harmless things, like where its own worktrees go. + - **GUARD-5.b** Only my own settings or my environment can loosen a safety setting. +- **GUARD-6** Running shell commands on my behalf is off until I turn it on myself. +- **GUARD-7** Scanning only ever visits the folders agents are known to use, so it can't be aimed at an arbitrary tree. +- **GUARD-8** A symlink leading out of the folder being scanned isn't followed. +- **GUARD-9** A folder I'm not allowed to read is skipped quietly instead of failing the whole search. +- **GUARD-10** A scan gives up on an enormous folder rather than grinding through it forever. +- **GUARD-11** The same refusals hold however let is reached, whether from a terminal, a tool call or a library. diff --git a/hi/history.md b/hi/history.md new file mode 100644 index 0000000..4299923 --- /dev/null +++ b/hi/history.md @@ -0,0 +1,23 @@ +--- +hi: 1 +families: [HISTORY] +--- + +# What you've been working on + +## Intent + +A plain answer to where my attention has actually been lately, across every coding agent at once. It should be built entirely from the fact that session files exist and when they last changed, never from a word inside them, and it should say so on its face. The default question is about this whole machine, because that is what people mean when they ask. + +## Criteria + +- **HISTORY-1** I can ask which coding agents I've actually been using lately. +- **HISTORY-2** I can ask which projects have been active lately, across every agent at once. +- **HISTORY-3** Whatever I touched most recently comes top of the list. + - **HISTORY-3.a** Things last touched at much the same time are ordered by how much activity they saw. +- **HISTORY-4** The report never opens a session file to build its answer. +- **HISTORY-5** The report states plainly that it read no transcripts. +- **HISTORY-6** By default the report covers this whole machine, because that's the question people mean. +- **HISTORY-7** I can narrow the report to the project I'm standing in. +- **HISTORY-8** A session whose project can be worked out from where it's filed is counted towards that project. +- **HISTORY-9** A session that can't be tied to any project is still counted towards its agent rather than dropped. diff --git a/hi/hosts.md b/hi/hosts.md new file mode 100644 index 0000000..eea6378 --- /dev/null +++ b/hi/hosts.md @@ -0,0 +1,27 @@ +--- +hi: 1 +families: [HOSTS] +--- + +# Every agent you use + +## Intent + +Each coding agent keeps its things in its own private layout, and knowing those layouts is most of what this tool is. The promise is coverage without ownership: recognise what Claude, Codex, Cursor, Grok, Gemini and Kimi have put on disk, credit each asset to the agent it came from, and leave all of it exactly where it is. An agent I don't have installed should simply be absent from the answer, and a portable agent document should count as much as a host's native folder. When coverage is the product, I should also be able to check what this machine actually offers before I trust an answer. + +## Criteria + +- **HOSTS-1** Nothing found is ever moved or copied out of the folder its agent put it in. +- **HOSTS-2** Claude Code's worktrees, skills, commands, plugins, tasks and sessions are found without me pointing at where they live. +- **HOSTS-3** Codex's linked checkouts, agents, plugins, memory and sessions are found the same way. +- **HOSTS-4** Cursor's skills, rules, commands, chats and plans are found the same way. +- **HOSTS-5** Grok's bundled skills, workflows, sessions and worktree registry are found the same way. +- **HOSTS-6** Gemini's instructions, history and knowledge stores are found the same way. +- **HOSTS-7** Antigravity's agents and sessions count as findable too, rather than falling between hosts. +- **HOSTS-8** Kimi Code's workspaces, sessions and history are found the same way. +- **HOSTS-9** An agent I don't have installed contributes nothing rather than breaking the answer. +- **HOSTS-10** An agent written as a single portable document counts as a real agent, not a stray markdown file. +- **HOSTS-11** Each skill inside such a document is offered as a skill in its own right. +- **HOSTS-12** Every result says which agent it came from, so I can tell one host's skill from another's. +- **HOSTS-13** I can check what let can actually see on this machine before I trust its answers. +- **HOSTS-14** That check names anything missing that let depends on, like git, instead of letting it fail later. diff --git a/hi/orient.md b/hi/orient.md new file mode 100644 index 0000000..b5493cf --- /dev/null +++ b/hi/orient.md @@ -0,0 +1,27 @@ +--- +hi: 1 +families: [ORIENT] +--- + +# Knowing where you are + +## Intent + +An agent that wakes up in a folder needs to know what that folder is before it does anything else. Standing in a checkout somewhere under an agent's home, I should be told which agent made it, which branch it's on, what the real project is, what else belongs to that project, and which instruction files apply. There should also be a way to hand a fresh agent a starter pack of that context in one call, small enough to paste into a prompt. That pack should never quietly include somebody's chat history. + +## Criteria + +- **ORIENT-1** I can ask what the folder I'm standing in actually is. + - **ORIENT-1.a** Asking about a path that isn't there says so rather than inventing an answer. + - **ORIENT-1.b** Standing somewhere that is no project at all, I'm told that plainly rather than handed a wrong project. +- **ORIENT-2** Standing inside an agent's worktree, I'm told which agent made it. +- **ORIENT-3** Standing inside a worktree, I'm told which branch it's on. +- **ORIENT-4** Standing in a worktree, the project I'm told about is the parent repository, not the worktree itself. +- **ORIENT-5** I'm shown the other worktrees that belong to the same project. +- **ORIENT-6** I'm shown the instruction files that apply where I'm standing. +- **ORIENT-7** Instruction files come back general first and closest to me last, so the most specific rules land on top. +- **ORIENT-8** I can ask about a path other than the one I'm standing in. +- **ORIENT-9** I can get a starter pack of project context in one call, small enough to hand straight to an agent. + - **ORIENT-9.a** I can ask for a fuller pack that includes the instruction text itself. + - **ORIENT-9.b** A fuller pack is capped so it can't swamp a context window. +- **ORIENT-10** A context pack never includes sessions or transcripts, however I ask for it. diff --git a/hi/route.md b/hi/route.md new file mode 100644 index 0000000..130ce37 --- /dev/null +++ b/hi/route.md @@ -0,0 +1,23 @@ +--- +hi: 1 +families: [ROUTE] +--- + +# Picking the right skill + +## Intent + +Nobody should have to grep a machine to find the skill they already installed. I describe the job in a sentence, and the skills most likely to do it come back ranked, each saying what it matched on and how to run it or read it. A skill that declares what it is for should beat one that merely happens to contain the word. No match at all should look like no match, not like a confident wrong answer. + +## Criteria + +- **ROUTE-1** I can describe a job in plain words and get back the skills most likely to do it, best first. +- **ROUTE-2** Each hit tells me which words it matched on. +- **ROUTE-3** Each hit comes with the command that runs it. +- **ROUTE-4** Each hit comes with the command that loads its full instructions. +- **ROUTE-5** A skill that declares trigger phrases beats one that merely happens to contain the word. +- **ROUTE-6** An agent's own idea of which of its skills fits wins over an outside guess. +- **ROUTE-7** A request that matches nothing comes back empty rather than with a confident wrong answer. +- **ROUTE-8** One common word buried in a long description doesn't push an unrelated skill to the top. +- **ROUTE-9** I can limit routing to one agent's skills. +- **ROUTE-10** Routing weighs every agent's skills at once, so the best one wins even when it belongs to an agent I'm not running. diff --git a/hi/show.md b/hi/show.md new file mode 100644 index 0000000..6168232 --- /dev/null +++ b/hi/show.md @@ -0,0 +1,31 @@ +--- +hi: 1 +families: [SHOW] +--- + +# Reading one thing at a time + +## Intent + +Finding is cheap and reading is expensive, so the two stay separate on purpose. A search hands back cards, and the full text arrives only when something decides it wants that one thing. Names should be enough to ask with, ambiguity should be reported rather than resolved by coin flip, and anything let won't read should still say what it is and why it stopped. + +## Criteria + +- **SHOW-1** A search hands me cards, never the full text of anything. +- **SHOW-2** I can load one thing's full text when I decide I want it. + - **SHOW-2.a** Each card carries an identifier I can hand straight back to load that thing. +- **SHOW-3** I can ask for a skill by its plain name instead of copying an identifier. +- **SHOW-4** A name that two things share tells me which ones it could have meant instead of picking one. + - **SHOW-4.a** When exactly one of those matches sits inside the folder I'm standing in, that's the one I get. +- **SHOW-5** Asking for something that isn't there says not found. +- **SHOW-6** Loading an agent gives me the text that says who it is. +- **SHOW-7** Loading an agent lists the skills it carries without dumping each one's body. +- **SHOW-8** Loading a worktree tells me which branch it sits on. + - **SHOW-8.a** A worktree whose folder is gone from disk is reported as missing rather than looking live. +- **SHOW-9** A file too large to hand over comes back as a capped opening section rather than not at all. + - **SHOW-9.a** A shortened body says plainly that it was cut short. +- **SHOW-10** I can point at any file path and be told what kind of agent asset it is. + - **SHOW-10.a** Opening a path gives me a short preview rather than the whole file. + - **SHOW-10.b** A file let won't read still tells me what kind of file it is. + - **SHOW-10.c** A file let won't read tells me why it stopped. +- **SHOW-11** Sessions, memory stores and task records come back as size and timestamp only. diff --git a/hi/wire.md b/hi/wire.md new file mode 100644 index 0000000..ae126c2 --- /dev/null +++ b/hi/wire.md @@ -0,0 +1,30 @@ +--- +hi: 1 +families: [WIRE] +--- + +# Using let from a program + +## Intent + +Most callers are agents rather than people, so every answer should be one predictable shape and every failure a reason a script can branch on. The same discovery should be reachable however a host prefers to reach it: as a command, as MCP tools, as a plugin of the project toolchain, or as a library import. Nothing about how it is called should change what it is willing to read. + +## Criteria + +- **WIRE-1** Every command can answer in JSON. + - **WIRE-1.a** Nothing but the answer is ever printed where a caller is reading. +- **WIRE-2** A person reading the terminal gets the answer without piping it through a JSON parser. +- **WIRE-3** Success and failure arrive in the same outer shape, so a caller never has to guess how to read it. +- **WIRE-4** A failure names its reason from a small fixed set instead of prose I'd have to pattern-match. +- **WIRE-5** The exit status matches the kind of failure, so a script can branch on it. +- **WIRE-6** An unexpected crash still comes back as a proper answer rather than a stack trace. +- **WIRE-7** Every answer says which version of let produced it. +- **WIRE-8** Every answer says how long the work took. +- **WIRE-9** I can run let as an MCP server so any agent can use it as tools. + - **WIRE-9.a** Those tools only ever read, so nothing an agent does through them changes my machine. + - **WIRE-9.b** A tool that fails reports the failure as a result instead of breaking the connection. + - **WIRE-9.c** Those tools default to the project I'm in, not the whole machine. +- **WIRE-10** I can install let into my project toolchain and call it like any other command there. + - **WIRE-10.a** Called that way, it works on the project the toolchain is pointed at without me repeating myself. +- **WIRE-11** I can import let into my own program and call the same discovery directly. +- **WIRE-12** Running let with nothing to do tells me what it can do. diff --git a/hi/workbed.md b/hi/workbed.md new file mode 100644 index 0000000..aec9b1d --- /dev/null +++ b/hi/workbed.md @@ -0,0 +1,32 @@ +--- +hi: 1 +families: [WORKBED] +--- + +# Your own working area + +## Intent + +Everything let finds belongs to somebody else. The workbed is the small patch that belongs to let: somewhere to make a worktree, keep a note, and write down a recipe of commands I keep repeating. It should always be optional, since discovery has to work perfectly well in a project that never sets one up. It should stay firmly inside its own boundaries, both when writing notes and when cleaning up worktrees. + +## Criteria + +- **WORKBED-1** I can set up let's own working area in a project with one command. + - **WORKBED-1.a** Running that again leaves whatever is already there alone. + - **WORKBED-1.b** Local runtime clutter stays out of version control by default. +- **WORKBED-2** Everything else works fine in a project that never sets one up. +- **WORKBED-3** I can make a worktree for a piece of work with a name and branch I could have predicted. + - **WORKBED-3.a** Making one where a folder already exists stops rather than overwriting it. + - **WORKBED-3.b** A branch that already exists is checked out rather than treated as a failure. +- **WORKBED-4** I can remove a worktree that let made. + - **WORKBED-4.a** A worktree another agent made is never let's to delete. +- **WORKBED-5** I can save a small note under a name of my choosing. +- **WORKBED-6** I can read a note back later by that name. + - **WORKBED-6.a** Asking for a note I never saved says not found. +- **WORKBED-7** I can keep notes for just this project or for everything I do on this machine. +- **WORKBED-8** Notes are only ever written inside let's own area. +- **WORKBED-9** I can write down a short recipe of the commands I keep repeating. + - **WORKBED-9.a** I can start from a worked example instead of a blank file. +- **WORKBED-10** I can list the recipes I've written down. +- **WORKBED-11** I can see the settings let is running with. + - **WORKBED-11.a** Each setting says where it came from, so I know which file to change.