{"id":45531267,"url":"https://github.com/cailmdaley/felt","last_synced_at":"2026-05-07T17:04:13.473Z","repository":{"id":332672440,"uuid":"1133373984","full_name":"cailmdaley/felt","owner":"cailmdaley","description":"Directory-contained markdown fibers with YAML frontmatter and wikilinks. A lightweight substrate for accumulating context — decisions, claims, tasks, questions, specs — and keeping it searchable, connected, and round-trippable through whatever tooling layers on top.","archived":false,"fork":false,"pushed_at":"2026-05-03T18:05:45.000Z","size":1884,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-03T19:33:43.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cailmdaley.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-13T09:02:09.000Z","updated_at":"2026-05-03T18:05:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cailmdaley/felt","commit_stats":null,"previous_names":["cailmdaley/felt"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/cailmdaley/felt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cailmdaley%2Ffelt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cailmdaley%2Ffelt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cailmdaley%2Ffelt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cailmdaley%2Ffelt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cailmdaley","download_url":"https://codeload.github.com/cailmdaley/felt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cailmdaley%2Ffelt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32747360,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-23T01:14:38.199Z","updated_at":"2026-05-07T17:04:13.432Z","avatar_url":"https://github.com/cailmdaley.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/banner.png\" alt=\"felt\" width=\"600\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/cailmdaley/felt/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/cailmdaley/felt/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"MIT License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# felt\n\nA CLI for the structured trail that builds up around work — decisions made, alternatives rejected, claims under test, tasks open, fragments waiting to consolidate. Each entry is a *fiber*: a directory under `.felt/` with a `\u003cslug\u003e.md` file inside, carrying YAML frontmatter and a plain-markdown body.\n\nThe directory tree gives hierarchy. `[[wikilinks]]` in bodies give narrative cross-references. YAML frontmatter holds structure (status, tags, decisions with excluded alternatives, inputs, insights), accreting as a fiber crystallizes. A rebuildable SQLite index at `.felt/index.db` makes the lot queryable — FTS5 over bodies, narrative back-references, reverse data-flow consumers — but plain markdown is the source of truth and the cache carries no extra authoring burden.\n\nFelt round-trips arbitrary YAML, so tool-owned namespaces (`shuttle:`, or anything else a downstream tool wants to attach) survive edits unchanged. A `.felt/` directory opens as a valid Obsidian vault out of the box (see [Obsidian](#obsidian)). The binary is a single static Go executable; no daemon, no required configuration.\n\nFelt is designed to be persistent memory for AI coding agents as much as for you. The bundled [Claude Code plugin](#agent-integration) and Codex hooks make `.felt/` the substrate agents reach for between sessions.\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/cailmdaley/felt/main/install.sh | sh\n```\n\nInstalls to `~/.local/bin` by default (or `/usr/local/bin` if writable). Override with `FELT_INSTALL_DIR`.\n\nAlso available via Homebrew (`brew install cailmdaley/tap/felt`) or from source (`go install github.com/cailmdaley/felt@latest`).\n\nUpdate to the latest release:\n\n```bash\nfelt update\n```\n\n### Agent setup\n\nFelt ships as a [Claude Code plugin](https://docs.claude.com/en/docs/claude-code/plugins) and a Codex skill bundle:\n\n```bash\nfelt setup claude                 # registers cailmdaley/felt marketplace, installs the plugin\nfelt setup codex                  # symlinks skills into ~/.agents/skills, configures Codex hooks\n```\n\n`setup claude` registers the felt marketplace from GitHub directly — Claude Code clones it, no local checkout required. Tagged felt binaries pin the plugin to the matching tag so the binary and the plugin stay aligned. `setup codex` reuses that clone for its own hook setup, so just running the two commands above is enough.\n\nThe plugin bundles two skills (`felt`, `ralph`), a SessionStart hook that lists active and recently touched fibers, and a PreToolUse hook that gates the first non-Skill tool call until the felt skill has been activated. See [Agent Integration](#agent-integration) for details.\n\n## Quick Start\n\n```bash\nfelt init                                              # creates .felt/ support files\nfelt add use-des-y3-weights \"Use DES Y3 weights\"       # file a decision\nfelt add covariance-estimation \"Covariance estimation\"\nfelt edit covariance-estimation -s closed -o \"switched to jackknife — 10x faster, \u003c2% bias\"\nfelt history covariance-estimation                     # append-only event log per fiber\n```\n\nA fiber can be anything: a task, a decision, a research claim, a question, a spec. The body carries detail, wikilinks cite related fibers, and the outcome captures the conclusion.\n\n```bash\nfelt show covariance-estimation        # inspect one fiber\nfelt tree                              # containment hierarchy\nfelt ls -s all \"jackknife\"             # search across everything\n```\n\n## Fibers\n\nA fiber is stored as `.felt/\u003cpath\u003e/\u003cslug\u003e.md`. For example:\n\n```yaml\n---\nname: Covariance estimation\nstatus: closed\ntags: [pure-eb, methods]\ncreated-at: 2026-01-15T10:30:00Z\nclosed-at: 2026-01-16T14:20:00Z\noutcome: \"Jackknife covariance, 10x faster than analytic, \u003c2% bias at all scales\"\n---\n\nTried analytic first — too slow for the number of bins we need.\nJackknife on 150 patches gives stable diagonal + off-diagonal.\n\nSee also [[use-des-y3-weights]].\n```\n\nIDs are slug paths such as `covariance-estimation` or `bao-analysis/damping-prior`. Bare slugs resolve when globally unique, so `felt show damping-prior` and `felt show bao-analysis/damping-prior` both work when unambiguous.\n\n### Status\n\nStatus is opt-in. Most fibers don't need it. Add `-s open` when something needs tracking.\n\n```\n· untracked    just a fiber\n○ open         tracked, not started\n◐ active       in progress\n● closed       done — outcome captured\n```\n\n### Tags\n\n```bash\nfelt add fix-bug \"Fix bug\" -t pure-eb -t urgent\nfelt edit covariance-estimation --tag note\nfelt ls -t pure-eb                        # filter by tag\nfelt ls -t tapestry:                      # prefix match\n```\n\nFor backward compatibility, felt also extracts `[tag]` prefixes from the slug argument:\n\n```bash\nfelt add \"[pure-eb] covariance-estimation\" \"Covariance estimation\"\n```\n\n### Relationships\n\nContainment comes from the directory tree. Narrative connections live in `[[wikilinks]]` inside the body. Structured `inputs.from` references express data flow when a fiber becomes computationally formalized. Felt indexes both edge types in SQLite, so `felt show` can surface narrative back-references and reverse data-flow consumers, while `felt ls --body` uses FTS instead of hydrating every body file.\n\n```bash\nfelt tree                               # containment hierarchy\nfelt show covariance-estimation         # body refs + citations + reverse consumers + frontmatter summary\nfelt ls \"DES Y3\"                        # search names, outcomes, structured fields\nfelt ls --body \"jackknife patches\"      # FTS5 body search\n```\n\n### Structured Frontmatter\n\nFibers can carry structured frontmatter — decisions with excluded alternatives, inputs and outputs with recipes, insights backed by evidence — alongside felt's native fields. These accrete as work crystallizes and are searchable through `felt ls`. Felt round-trips them opaquely; downstream tools project meaning onto them.\n\n```yaml\n---\nname: BAO Damping Prior\noutcome: Informative Gaussian priors confirmed.\ninputs:\n  - id: clustering_data\n    type: data\n    from: parent.desi_dr1_vac\ndecisions:\n  damping_prior:\n    label: BAO Damping Prior\n    default: gaussian\n    options:\n      gaussian:\n        label: Informative Gaussian\n---\n```\n\n```bash\nfelt ls \"BAO\"                 # name, outcome, and structured fields\nfelt check                    # broken refs/fragments, legacy format residue, formalization drift\n```\n\n### History\n\nEach fiber carries an append-only event log — editorial summaries, reviews, mechanical add/edit/rm, and external_edit detection — for chronological handoff across sessions and tools.\n\n```bash\nfelt history \u003cid\u003e                              # editorial chain (newest first)\nfelt history \u003cid\u003e --last 1                     # what the previous session left\nfelt history \u003cid\u003e --mechanical                 # + add/edit/rm/external_edit\nfelt history append \u003cid\u003e --summary \"...\"       # log session continuity\n```\n\n### Progressive Disclosure\n\n```bash\nfelt show \u003cid\u003e                    # full body + metadata\nfelt show \u003cid\u003e -d name            # name + tags only\nfelt show \u003cid\u003e -d compact         # metadata + outcome + frontmatter counts\nfelt show \u003cid\u003e -d summary         # compact + citations/consumers + lede + frontmatter summary\nfelt show \u003cid\u003e --body             # body + body start line for editing\nfelt show \u003cid\u003e --citations        # indexed narrative back-references only\nfelt show \u003cid\u003e --consumers        # indexed reverse data-flow consumers only\nfelt show \u003cid\u003e --decision cov     # one structured decision as YAML/JSON\nfelt show \u003cid\u003e --inputs           # structured inputs only\n```\n\n## Obsidian\n\nA `.felt/` directory is a valid Obsidian vault. Open it in Obsidian for a GUI browser with backlinks, graph view, and full-text search; felt's `[[wikilinks]]` are the Obsidian format. Structured frontmatter fields (`decisions`, `inputs`, `outputs`, `insights`, `tempered`) are queryable with [Dataview](https://github.com/blacksmithgu/obsidian-dataview):\n\n```dataview\nTABLE status, outcome\nFROM \".\"\nWHERE tempered = true\n```\n\nIntegration is rudimentary today and aspirational to improve. The basics work: the vault opens, wikilinks click through, frontmatter renders, and Dataview queries run over the structured fields. Known rough edges: fragment wikilinks to nested elements (`[[slug#decision-name]]`) do not resolve because Obsidian expects headings, and the per-fiber directory nesting (`slug/slug.md`) means browsing is two clicks per fiber unless you install a Folder Note plugin.\n\nObsidian is not a dependency. The CLI and the `.felt/` tree are the source of truth; use them separately or together.\n\n## Agent Integration\n\n`felt setup claude` registers the felt plugin marketplace from GitHub and installs the `felt` plugin via Claude Code's CLI:\n\n```\nclaude plugin marketplace add cailmdaley/felt#v\u003cversion\u003e\nclaude plugin install felt@cailmdaley-felt\n```\n\nTagged felt binaries pin to their matching git tag; `dev` builds track the default branch. Claude Code clones the marketplace to `~/.claude/plugins/marketplaces/cailmdaley-felt/`, so no local checkout of felt is required. Pass `--source \u003cpath\u003e` for development against an unreleased checkout.\n\nThe plugin bundles two skills (`felt`, `ralph`), SessionStart/PreToolUse hooks, and a launcher script for ralph loops.\n\nFor Codex (no plugin manifest support), `felt setup codex` symlinks the same skills into `~/.agents/skills/` and configures Codex's `hooks.json` to invoke the same hook scripts the plugin uses. It reuses Claude Code's marketplace clone, so running `felt setup claude` first means `setup codex` works without `--source`.\n\nSkills can also be linked into other locations independently:\n\n```bash\nfelt setup skills                                # links felt and ralph to ~/.claude/skills\nfelt setup skills --target ~/.agents/skills      # link skills elsewhere\nfelt setup skills --source \u003cpath\u003e                # use a specific plugin directory as source\n```\n\n### Bundled Skills\n\n| Skill | Purpose |\n|-------|---------|\n| **felt** | Filing fibers — formalizing as you work, crafting decisions and constitutions, mining at session end, maintenance passes, transcript processing |\n| **ralph** | Executing autonomous iteration loops over a constitution — launch script + in-loop protocol |\n\n### Hooks\n\n| Hook | Behavior |\n|------|----------|\n| **SessionStart** | Prints an \"activate the felt skill first\" directive plus active and recently touched fibers from the project's `.felt/` |\n| **PreToolUse** | Gates the first non-Skill tool call until the felt skill has been activated (so the agent loads the practice — philosophy, references — not just the cheatsheet). Sibling skill activation (shuttle, ralph) doesn't satisfy the gate; only `felt` does. Codex sessions are exempt. |\n\n## Commands\n\n```bash\n# Core\nfelt init                         felt add \u003cslug\u003e \u003cname\u003e [flags]\nfelt edit \u003cid\u003e [flags]            felt show \u003cid\u003e [-d level]\nfelt ls [query]                   felt check\nfelt history \u003cid\u003e                 felt history append \u003cid\u003e --summary \"...\"\nfelt tree                         felt nest|unnest \u003cid\u003e\nfelt migrate [--dry-run]          felt rm \u003cid\u003e\nfelt setup claude|codex|skills    felt update\n```\n\n### Flags\n\n```bash\n# felt add\n-b, --body \"text\"                 -s, --status open|active|closed\n-t, --tag \u003ctag\u003e                   -D, --due 2024-03-15\n-o, --outcome \"text\"\n\n# felt edit\n--name \"text\"                     --tag \u003ctag\u003e\n--untag \u003ctag\u003e                     --body \"text\"\n--outcome \"text\"\n--decision \u003cid\u003e --label \"text\"    --rationale \"text\"\n--default \u003coption-id\u003e             --option 'id:label[:excluded[:reason]]'\n--input 'id[:type[:from[:description]]]'\n--insight 'id:claim'\n\n# felt ls\n--body\n-e, --exact                       -r, --regex\n\n# felt history\n--last \u003cN\u003e                        --kind \u003ctype\u003e\n--mechanical                      --json\n\n# global\n-j, --json\n```\n\n## Inspirations\n\nFelt borrows from several projects exploring how to give AI coding agents structured, persistent context:\n\n- **[Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten)** — Niklas Luhmann's slip-box method, the ancestor of modern linked-note knowledge management. Emergent structure from connections rather than prescribed hierarchy. Felt's combination of directory containment, `[[wikilinks]]`, and ASTRA data-flow comes from this lineage, with Obsidian as the practical modern embodiment the vault format mirrors.\n- **[Beads](https://github.com/steveyegge/beads)** — Steve Yegge's graph-based, git-backed issue tracker designed as agent memory. The core conviction — that coding agents need structured persistent memory they can query, not just scratch files — is load-bearing for felt. Beads leans on Go, SQLite, and JSONL; felt leans on plain markdown with a rebuildable cache.\n- **[Dots](https://github.com/joelreymont/dots)** — Joel Reymont's minimalist counterpart to Beads (200 KB of Zig, plain markdown in `.dots/`, no database). The \"the directory tree is already the source of truth\" stance runs through felt too — the SQLite cache at `.felt/index.db` is strictly a rebuildable index, not storage.\n- **[Ralph Wiggum](https://github.com/ghuntley/how-to-ralph-wiggum)** — Geoffrey Huntley's autonomous iteration technique: feed the agent the same spec on a loop until the work is done. Felt's `ralph` skill, the `constitute` activity, and the `constitute.md` reference (pointers not snapshots, desired state, living document) all come from this idea.\n- **[Ouroboros](https://github.com/Q00/ouroboros)** — Q00's specification-first AI coding workflow. The Double Diamond rhythm (Wonder → Ontology, Design → Delivery), the stance personas, and the qualitative ambiguity self-check in the `crafting.md` reference are adapted from Ouroboros's interview phase — with the numerical ambiguity scoring, immutable seed specs, and ontology-convergence stopping criterion explicitly rejected as the wrong shape for scientific work.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcailmdaley%2Ffelt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcailmdaley%2Ffelt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcailmdaley%2Ffelt/lists"}