ai-startup-skills
创业公司做 AI 产品的 7 步 Agent Skill 合集:验证 → BP → 政策 → 路演 → 获客 → 定价 → 注册。
Translation pending
Every answer is JSON, every refusal has a rule, and no binary can do more than its authority says.
OtherPython · CGitHub @alpibruslOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Nine small command-line tools for AI agents, written in cancho: seek, list, peek, jsonq, tally, hash, write, replace, move. JSON output, errors that name a rule, and a compiler-proven authority per binary.
Taken from the repository README
Loading the full README.
Read the full README ↗Ten small tools that AI agents and scripts can rely on, and one opt-in. seek, list, peek, jsonq, tally, hash, write, replace, move and archive do the everyday work of grep, ls/find, sed -n, jq, sort | uniq -c, sha256sum, a careful cp/mv and tar/gzip, and run starts a program from a directory you chose, with explicit semantics, bounded resources, tagged refusals that often carry a repair, and a checkable authority row per binary. Every answer is JSON against a published schema, and every tool describes itself (introspect, skill); an MCP server serves them to an agent runtime from that same description. Written in cancho. The project page has one page per tool.
Status: early, ten tools and one opt-in built and tested. Not claimed: that agents do better with these tools than with the incumbents. That needs an agent-in-the-loop evaluation (cancho#228) that has not been run. What is claimed is what the conformance gates check. What is missing is listed under "What it cannot do".
| Tool | Instead of | Does |
|---|---|---|
seek | grep -F -n -b | literal search over files, a stream of matches |
list | ls, find, tree | the entries beneath a directory, sorted, depth-bounded, links never followed |
peek | sed -n, head, tail, wc -l | a range of lines or bytes, with numbers and a cursor |
jsonq | jq -c | one value from one strict JSON document, by RFC 6901 pointer |
tally | sort | uniq -c | sort -rn | distinct lines or fields, counted and ranked |
hash | sha256sum, sha512sum | file digests of any size, --verify |
write | cp, >, tee | replace a file atomically, only if it holds what the caller says |
replace | sed -i | replace exact text an expected number of times, atomically |
move | mv | rename a file or directory in place, never over an existing name |
archive | tar, gzip, unzip, zstd | list, extract and create tar archives, gzip- or zstd-compressed or not, and zips; read bzip2 and xz; checked whole before any file is written (docs/archive.md) |
run | exec, timeout | opt-in: start one program from the deployer's directory with exact arguments, a fixed environment, a deadline and an output cap (docs/next-tools.md section 3) |
Two agents read notes.txt and each adds a line. With plain writes the second write wins and agent A's line is gone, and nobody is told:
$ printf 'shopping list\n- milk (agent A)\n' > notes.txt # agent A
$ printf 'shopping list\n- bread (agent B)\n' > notes.txt # agent B
$ cat notes.txt
shopping list
- bread (agent B)
With guarded writes (write --if-sha256) the stale write is refused, and the refusal carries what the agent needs to retry (selected fields of each JSON line):
$ hash --root . notes.txt # A and B both read it: H1 is its hash
{"type":"hash","path":"notes.txt","algo":"sha256","hex":"936bb8ff57a0…","bytes":14}
$ ... | write --root . --if-sha256 H1 --stdin notes.txt # agent A adds its line
{"path":"notes.txt","changed":true,"bytes":31,"after_sha256":"7bde7db5f30a…"}
$ ... | write --root . --if-sha256 H1 --stdin notes.txt # agent B, stale
{"rule":"precondition.hash-mismatch","hint":"re-read the file, then decide","repair":{"kind":"none","reason":"the file changed since it was read; re-read, then decide"},"detail":{"path":"notes.txt","expected_sha256":"936bb8ff57a0…","actual_sha256":"7bde7db5f30a…","size":31}}
# exit status 5
$ ... | write --root . --if-sha256 H2 --stdin notes.txt # agent B re-reads (H2 came with the refusal), re-applies, retries
{"path":"notes.txt","changed":true,"bytes":49,"after_sha256":"60e7843a980c…"}
$ cat notes.txt
shopping list
- milk (agent A)
- bread (agent B)
The full transcript, with every JSON line as printed, is in docs/reference.md.
grep, sed and jq were made for a person at a terminal, who reads the prose and retries. An agent has to parse text, often cannot see stderr, and decides its next step from what came back. Each bullet is a property the gates check, with where to see it.
schemas/). A path, a line number and a byte offset are fields; bytes that are not UTF-8 come back as {"b64": …}, never replaced.end record, so a stream without one was cut short. A capped answer says truncated: true and gives a next cursor to resume exactly there.{code, rule, message, hint, repair, detail}; match on rule. When the fix is mechanical, repair is an argv to run as it stands, and a repair never widens what the tool may touch. seek introspect lists the rules and exit codes.write needs --create or --if-sha256 of what it read, and replace needs the text to occur --expect times: a stale view is precondition.hash-mismatch, not a lost edit. Writes are atomic, locked and idempotent, and --dry-run shows the diff.--root. .., absolute and outside paths are refused before anything is opened, and no link below the root is followed (path.symlink).--max-line-bytes: about 1.7 MB whether the file is 1 MiB or 256 MiB (reference).introspect prints the flags, rules, exit codes, limits, schema and guarantees as JSON; skill prints a guide for an agent. Both come from the tables the parser runs on, so they cannot drift.tools.toml.You need git, Rust and clang. On a 16-core Mac with Rust installed and its dependencies already downloaded, the compiler built in 17 seconds and the first nine tools in 7; the clones and a first-time dependency download are extra, so allow a few minutes the first time.
git clone https://github.com/alpibrusl/cancho
git clone https://github.com/alpibrusl/cancho-tools && cd cancho-tools
REV=$(sed -n 's/^cancho *= *"\([0-9a-f]*\)".*/\1/p' cancho.toml) # the compiler these sources need
(cd ../cancho && git fetch -q origin && git checkout "$REV" && cargo build --release -p cancho)
export PATH=$PWD/../cancho/target/release:$PWD/build:$PATH
cancho build # every tool into build/
seek --root . --format text 'fn main' tools/seek/seek.cho # try one
seek introspect # flags, rules, limits, schema, authority (JSON)
One real command per tool, on a small project (src/main.rs, package.json, access.log). Every tool takes --root .: paths are relative to it and nothing outside can be reached. The output is what the built tools print, with long hashes shortened.
seek: search files for literal text.
$ seek --root . add src/main.rs
{"type":"match","path":"src/main.rs","line":2,"offset":12,"text":" let total = add(2, 3);"}
{"type":"match","path":"src/main.rs","line":6,"offset":69,"text":"fn add(a: i32, b: i32) -> i32 {"}
{"type":"file","path":"src/main.rs","matches":2,"bytes":113,"binary":false,"complete":true}
{"type":"end","ok":true,"command":"seek","schema":"seek.v1","complete":true,"files":1,"matches":2,"errors":0,"truncated":false,"next":null}
list: the entries beneath a directory.
$ list --root . --depth 2 --format text
access.log
package.json
src/
src/main.rs
peek: a range of lines, with numbers.
$ peek --root . --lines 2:3 --format text src/main.rs
2 let total = add(2, 3);
3 println!("{}", total);
jsonq: one value from a JSON document.
$ jsonq --root . -p /deps/serde package.json
{"ok":true,"command":"jsonq","schema":"jsonq.v1","data":{"pointer":"/deps/serde","kind":"string","value":"1.0"},"meta":{"version":"0.1.0"}}
tally: count and rank a field.
$ tally --root . --field 3 --delim ' ' --format text access.log
3 200
1 404
1 500
hash: a file's SHA-256.
$ hash --root . package.json
{"type":"hash","path":"package.json","algo":"sha256","hex":"2c313334b372…","bytes":78}
{"type":"end","ok":true,"command":"hash","schema":"hash.v1","complete":true,"files":1,"errors":0}
write: create a file, or replace it only if it is what you think.
$ printf 'hello\n' | write --root . --create --stdin NOTES.md
{"ok":true,"command":"write","schema":"write.v1","data":{"path":"NOTES.md","changed":true,"created":true,"bytes":6,"before_sha256":null,"after_sha256":"5891b5b522d5…","diff":[{"old_start":1,"new_start":1,"removed_count":0,"added_count":1,"removed":[],"added":["hello\n"]}],"diff_truncated":false},"meta":{"version":"0.1.0"}}
replace: change exact text, here as a dry run.
$ replace --root . --old 'a + b' --new 'a.wrapping_add(b)' --dry-run src/main.rs
{"ok":true,"command":"replace","schema":"replace.v1","data":{"path":"src/main.rs","changed":false,"replacements":1,"bytes":125,"before_sha256":"98ace4483c48…","after_sha256":"63261420d975…","diff":[{"old_start":7,"new_start":7,"removed_count":1,"added_count":1,"removed":[" a + b\n"],"added":[" a.wrapping_add(b)\n"]}],"diff_truncated":false},"dry_run":true,"planned_actions":[{"op":"replace","path":"src/main.rs","replacements":1,"before_sha256":"98ace4483c48…","after_sha256":"63261420d975…","bytes":125,"diff":[{"old_start":7,"new_start":7,"removed_count":1,"added_count":1,"removed":[" a + b\n"],"added":[" a.wrapping_add(b)\n"]}],"diff_truncated":false}],"meta":{"version":"0.1.0"}}
# exit status 9
move: rename in place, never over an existing name.
$ move --root . --dry-run NOTES.md NOTES-2026.md
{"ok":true,"command":"move","schema":"move.v1","data":{"path":"NOTES.md","to":"NOTES-2026.md","changed":false,"kind":"file","sha256":null},"dry_run":true,"planned_actions":[{"op":"move","path":"NOTES.md","to":"NOTES-2026.md","kind":"file","sha256":null}],"meta":{"version":"0.1.0"}}
# exit status 9
archive: a tarball, byte for byte the same every time, here as a dry run.
$ archive --root . --op create --dry-run project.tgz src package.json
{"type":"dir","path":"src"}
{"type":"file","path":"src/main.rs","bytes":113,"sha256":"98ace4483c48…"}
{"type":"file","path":"package.json","bytes":78,"sha256":"2c313334b372…"}
{"type":"end","ok":true,"command":"archive","schema":"archive.v1","complete":true,"op":"create","format":"tgz","entries":3,"bytes":191,"errors":0,"dry_run":true,"archive_sha256":"372e8efb591b…"}
# exit status 9
Flags, more examples, and each tool's rules are in docs/reference.md.
server/mcp.cho serves the ten default tools over MCP (run only if the server is built with --with run) (stdio, protocol 2025-06-18). tools/list is generated from each tool's introspect, and a tools/call runs the binary and answers with its output byte for byte. It may start the binaries in the one directory it was built with, and nothing else; --root is the server's, never the model's.
python3 scripts/mcp.py build --bin "$PWD/build" --out build/mcp
build/mcp --root /path/to/workspace
Design and measurements: docs/mcp.md.
What "designed for agents" means here, what a test checks on every binary, and what is not checked: docs/agent-first.md.
move --remove --if-sha256 HEX renames it to a tombstone in the same directory, and move NAME.removed-… NAME undoes it.curl or ssh: a network tier would be a separate project with its own authority ceiling, docs/archive.md section 9). seek is literal text; jsonq takes pointers, not jq filters.move takes a new name, not a new directory.seek takes named files, not a directory: list then seek is the pattern for now.run, which is opt-in, holds exec for its programs directory and a clock for its deadline, and says it is irreversible-consequential. No other tool's authority holds them (tools.toml).archive holds the archive in memory, up to --max-bytes, so its memory is that bound and not a constant. extract makes the directories an entry needs beneath --into, never --into itself (docs/archive.md section 13). It does not write bzip2 or xz.The list of open work is in issues.
Supporting evidence: these tools are not built to win on speed, and mostly do not lose. A 64 MiB text file, through a pipe, minimum of 7 interleaved rounds, Linux x86-64 on a shared machine; speed is reported, not gated.
| Command | cancho-tools | Incumbent |
|---|---|---|
seek gamma (about a million matches) | 0.49 s | grep -F -n -b 0.51 s, rg 0.39 s |
seek with no match | 0.04 s | grep -F -n -b 0.04 s |
hash (SHA-256) | 0.52 s | sha256sum 0.17 s |
peek --count-lines --lines 1:100 | 0.08 s | sed -n 1,100p; wc -l 0.13 s |
tally --field 1 | 0.16 s | cut | sort | uniq -c | sort | head 0.68 s |
jsonq -p /0, 16 MiB array | 0.14 s | jq -c .[0] 0.73 s |
list, one directory of 100,000 files | 0.144 s | find -printf 0.146 s, ls -1 0.154 s |
sha256sum's lead is OpenSSL's hand-written assembly, which cancho has no way to express. More rows (seek -i is 0.58 s against 0.52 s), startup and --root cost: docs/reference.md. Measure on your machine: python3 scripts/toolbench.py --tool seek --size 64MiB.
| project page | one page per tool, generated from the tool itself: flags, rules, exit codes, authority, JSON schemas and a ready-made SKILL.md |
| docs/reference.md | every tool with its examples, the error protocol, confinement, authority, memory, performance, the package, development |
| docs/mcp.md | the MCP server: design and measurements |
| docs/history.md | how this was built, what it found in the compiler, the performance rounds |
cancho's docs/agent-toolbox.md | the design (epic cancho#214) |
| cancho-table | a tenth tool, built outside this repository on its contract package |
Every change goes through what CI runs: cancho fmt --check contract tools tests generated server, cancho build, cancho test, scripts/schemas.py --check, scripts/manifest.py --check, scripts/demo_race.py --check, scripts/package.py --check, scripts/mcp.py --check, scripts/cli_mutants.py --check (the mutants of the table scans), the conformance tests. A change that needs a new effect fails until tools.toml allows it. After changing a tool, run python3 scripts/manifest.py and cancho build; after changing what a tool prints, python3 scripts/demo_race.py --update-readme rewrites the generated sections of this file. Layout, the gates and how to build more tools on the contract package: docs/reference.md.