@hasna/files 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +148 -0
  2. package/dashboard/dist/assets/index-DBpbr5zm.css +1 -0
  3. package/dashboard/dist/assets/index-zazl9Rbx.js +129 -0
  4. package/dashboard/dist/index.html +13 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +46386 -0
  8. package/dist/db/collections.d.ts +8 -0
  9. package/dist/db/collections.d.ts.map +1 -0
  10. package/dist/db/database.d.ts +5 -0
  11. package/dist/db/database.d.ts.map +1 -0
  12. package/dist/db/files.d.ts +12 -0
  13. package/dist/db/files.d.ts.map +1 -0
  14. package/dist/db/machines.d.ts +6 -0
  15. package/dist/db/machines.d.ts.map +1 -0
  16. package/dist/db/peers.d.ts +15 -0
  17. package/dist/db/peers.d.ts.map +1 -0
  18. package/dist/db/projects.d.ts +8 -0
  19. package/dist/db/projects.d.ts.map +1 -0
  20. package/dist/db/resolve.d.ts +9 -0
  21. package/dist/db/resolve.d.ts.map +1 -0
  22. package/dist/db/search.d.ts +6 -0
  23. package/dist/db/search.d.ts.map +1 -0
  24. package/dist/db/sources.d.ts +17 -0
  25. package/dist/db/sources.d.ts.map +1 -0
  26. package/dist/db/tags.d.ts +8 -0
  27. package/dist/db/tags.d.ts.map +1 -0
  28. package/dist/index.d.ts +15 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +43739 -0
  31. package/dist/lib/config.d.ts +13 -0
  32. package/dist/lib/config.d.ts.map +1 -0
  33. package/dist/lib/hasher.d.ts +3 -0
  34. package/dist/lib/hasher.d.ts.map +1 -0
  35. package/dist/lib/ignore.d.ts +11 -0
  36. package/dist/lib/ignore.d.ts.map +1 -0
  37. package/dist/lib/indexer.d.ts +3 -0
  38. package/dist/lib/indexer.d.ts.map +1 -0
  39. package/dist/lib/s3.d.ts +12 -0
  40. package/dist/lib/s3.d.ts.map +1 -0
  41. package/dist/lib/sync.d.ts +19 -0
  42. package/dist/lib/sync.d.ts.map +1 -0
  43. package/dist/lib/watcher.d.ts +5 -0
  44. package/dist/lib/watcher.d.ts.map +1 -0
  45. package/dist/mcp/index.d.ts +3 -0
  46. package/dist/mcp/index.d.ts.map +1 -0
  47. package/dist/mcp/index.js +55905 -0
  48. package/dist/server/index.d.ts +3 -0
  49. package/dist/server/index.d.ts.map +1 -0
  50. package/dist/server/index.js +42191 -0
  51. package/dist/server/serve.d.ts +2 -0
  52. package/dist/server/serve.d.ts.map +1 -0
  53. package/dist/types/index.d.ts +104 -0
  54. package/dist/types/index.d.ts.map +1 -0
  55. package/package.json +77 -0
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @hasna/files
2
+
3
+ Agent-first file management — index local folders and S3 buckets, tag, search, and retrieve files via CLI + MCP.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun install -g @hasna/files
9
+ ```
10
+
11
+ ## CLI
12
+
13
+ ```bash
14
+ # Add sources
15
+ files sources add ./my-documents
16
+ files sources add s3://my-bucket --region us-east-1 --access-key KEY --secret-key SECRET
17
+
18
+ # Index
19
+ files index # index all sources on this machine
20
+ files index src_abc123 # index one source
21
+
22
+ # Search & list
23
+ files search "invoice 2024"
24
+ files list --tag important --ext pdf
25
+ files list --source src_abc123
26
+
27
+ # File operations
28
+ files info f_abc123
29
+ files tag f_abc123 invoice important
30
+ files untag f_abc123 invoice
31
+ files download f_abc123 # downloads to ~/Downloads/<name>
32
+ files upload ./report.pdf src_abc123
33
+
34
+ # Organize
35
+ files collections create "Q1 Reports"
36
+ files collections add col_abc123 f_abc123
37
+ files projects create "Tax 2025"
38
+ files projects add prj_abc123 f_abc123
39
+
40
+ # Multi-machine sync
41
+ files sync http://192.168.1.10:19432
42
+
43
+ # Info
44
+ files machines
45
+ files tags
46
+ files sources list
47
+ files db # show DB path
48
+ ```
49
+
50
+ ## MCP Server
51
+
52
+ Add to your `claude_desktop_config.json` or `.mcp.json`:
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "files": {
58
+ "command": "files-mcp"
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### MCP Tools
65
+
66
+ | Tool | Description |
67
+ |------|-------------|
68
+ | `list_sources` | List configured sources |
69
+ | `add_source` | Add local or S3 source |
70
+ | `remove_source` | Remove a source |
71
+ | `index_source` | Re-index source(s) |
72
+ | `list_files` | List files with filters |
73
+ | `search_files` | Full-text search |
74
+ | `get_file` | Get file details |
75
+ | `download_file` | Download file to disk |
76
+ | `upload_file` | Upload file to S3 |
77
+ | `list_tags` | List all tags |
78
+ | `tag_file` | Tag a file |
79
+ | `untag_file` | Remove tags |
80
+ | `list_collections` | List collections |
81
+ | `create_collection` | Create collection |
82
+ | `add_to_collection` | Add file to collection |
83
+ | `list_projects` | List projects |
84
+ | `create_project` | Create project |
85
+ | `add_to_project` | Add file to project |
86
+ | `list_machines` | List known machines |
87
+
88
+ ## REST API
89
+
90
+ ```bash
91
+ files-serve # starts on port 19432
92
+ files-serve --port 8080
93
+ ```
94
+
95
+ | Endpoint | Method | Description |
96
+ |----------|--------|-------------|
97
+ | `/sources` | GET, POST | List / create sources |
98
+ | `/sources/:id` | DELETE | Remove source |
99
+ | `/sources/:id/index` | POST | Index source |
100
+ | `/files` | GET | List/search files (`?q=`, `?tag=`, `?ext=`, `?source_id=`) |
101
+ | `/files/:id` | GET | Get file |
102
+ | `/files/:id/download` | GET | Download file |
103
+ | `/files/:id/tags` | POST, DELETE | Tag / untag |
104
+ | `/tags` | GET | List tags |
105
+ | `/collections` | GET, POST | List / create |
106
+ | `/collections/:id/files` | POST | Add file |
107
+ | `/collections/:id/files/:fid` | DELETE | Remove file |
108
+ | `/projects` | GET, POST | List / create |
109
+ | `/projects/:id/files` | POST | Add file |
110
+ | `/machines` | GET | List machines |
111
+ | `/machines/current` | GET | Current machine |
112
+ | `/sync` | POST | Sync from peers `{ peers: ["http://..."] }` |
113
+ | `/health` | GET | Health check |
114
+
115
+ ## Dashboard
116
+
117
+ ```bash
118
+ files-serve # then open http://localhost:19432
119
+ ```
120
+
121
+ Or in dev: `cd dashboard && bun run dev`
122
+
123
+ ## Multi-machine sync
124
+
125
+ Each machine has its own SQLite database at `~/.files/files.db`. To sync file indexes between machines:
126
+
127
+ ```bash
128
+ # On machine B, pull from machine A
129
+ files sync http://machine-a.local:19432
130
+
131
+ # Or via API
132
+ curl -X POST http://localhost:19432/sync \
133
+ -H "Content-Type: application/json" \
134
+ -d '{"peers": ["http://machine-a.local:19432"]}'
135
+ ```
136
+
137
+ This merges remote file records into your local DB so you can search across all machines.
138
+
139
+ ## Storage
140
+
141
+ - **SQLite DB**: `~/.files/files.db` (override with `FILES_DB_PATH`)
142
+ - **Data dir**: `~/.files/` (override with `FILES_DATA_DIR`)
143
+ - **S3 credentials**: stored per source in the DB config column (JSON)
144
+ - **Hashing**: BLAKE3 via `@noble/hashes`
145
+
146
+ ## License
147
+
148
+ MIT
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-900:oklch(37.8% .077 168.94);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-900:oklch(35.9% .144 278.697);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.sticky{position:sticky}.top-0{top:calc(var(--spacing) * 0)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-auto{margin-top:auto}.mr-1{margin-right:calc(var(--spacing) * 1)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-2{margin-left:calc(var(--spacing) * 2)}.flex{display:flex}.table{display:table}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.h-full{height:100%}.h-screen{height:100vh}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-20{width:calc(var(--spacing) * 20)}.w-52{width:calc(var(--spacing) * 52)}.w-64{width:calc(var(--spacing) * 64)}.w-96{width:calc(var(--spacing) * 96)}.w-full{width:100%}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-800\/50{border-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.border-slate-800\/50{border-color:color-mix(in oklab,var(--color-slate-800) 50%,transparent)}}.bg-emerald-900\/50{background-color:#004e3b80}@supports (color:color-mix(in lab,red,red)){.bg-emerald-900\/50{background-color:color-mix(in oklab,var(--color-emerald-900) 50%,transparent)}}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-indigo-900\/20{background-color:#312c8533}@supports (color:color-mix(in lab,red,red)){.bg-indigo-900\/20{background-color:color-mix(in oklab,var(--color-indigo-900) 20%,transparent)}}.bg-indigo-900\/50{background-color:#312c8580}@supports (color:color-mix(in lab,red,red)){.bg-indigo-900\/50{background-color:color-mix(in oklab,var(--color-indigo-900) 50%,transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-transparent{background-color:#0000}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-12{padding-block:calc(var(--spacing) * 12)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.whitespace-nowrap{white-space:nowrap}.text-emerald-400{color:var(--color-emerald-400)}.text-indigo-300{color:var(--color-indigo-300)}.text-indigo-400{color:var(--color-indigo-400)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-60{opacity:.6}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-slate-500::placeholder{color:var(--color-slate-500)}@media(hover:hover){.hover\:bg-indigo-500:hover{background-color:var(--color-indigo-500)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-slate-800\/30:hover{background-color:#1d293d4d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-800\/30:hover{background-color:color-mix(in oklab,var(--color-slate-800) 30%,transparent)}}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:text-white:hover{color:var(--color-white)}}.focus\:border-indigo-500:focus{border-color:var(--color-indigo-500)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}}*{box-sizing:border-box}body{color:#e2e8f0;background:#0f172a;margin:0;font-family:system-ui,-apple-system,sans-serif}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}