Releases: KhaytApp/khayt-mac
Release list
Khayt for macOS 4.0.0-alpha.9
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Changed
-
The Mac signs in to the cloud itself.
settings.cloud.tokenis a session
token the server issues at login, sealed against the Keychain of the machine
that asked for it — so a shop's book carried to a new Mac arrives with a token
nothing on that Mac can read, every cloud feature goes quiet, and the only
cure was to open the other app. Book → Sign in to the cloud asks for the
server, the account, its password and the sync passphrase, and does the rest
here.The passphrase is checked before anything is written: a token saved beside
a key that does not open leaves a shop connected and unable to read a word of
its own cloud, which reads as the server having lost it. The new token is
sealed the way the other app seals it, andsettings.cloudis written in the
same shape, so both apps read each other's sign-in.Everything after the token already worked — pulling, unlocking, comparing,
pushing. This was one missing call, and it was the difference between a Mac
that keeps a shop's book and one that needs another app to stay reachable. -
The Mac refreshes the customer's tracking link, so a published job can be
moved here at all. A job published to the portal could not be moved on the
Mac: the app refuses a move it cannot carry out whole, and the refresh — a
cloud write — was one it could not make. So a shop that had published
anything could not run its board on this app, which is the one thing the
board is for. The link is refreshed from here now, through the same rule the
other app uses (lib/portal-refresh.js): the same payload, the same guards,
the same path. A refresh that fails says so rather than leaving a customer
reading "Printing" about a job that was collected yesterday.That was the last entry on the list of things this app sends you elsewhere
for, apart from SMTP mail. -
A shop whose portal trial had lapsed was refused moves for a message
nobody was going to get. The rule that decides where a move reaches never
looked at the trial, while the code that actually publishes returns early
when it has run out. So the two disagreed: one said the move reached the
customer's link, the other would have sent nothing — and on the Mac that
disagreement is a move refused outright. Both halves ask one rule now. (No
shop is affected today: while the beta is free every trial is active.) -
The Mac can email the customer, so it stops refusing the move. A job
whose next stage tells the customer by email could not be moved on the Mac at
all: the app refuses a move it cannot carry out whole — rightly, because a
half-made move leaves somebody untold while the book says otherwise — and it
had no way to send one. It sends through SendGrid and Mailgun now, and
the message is not a second app's idea of one: the subject, the body and the
decision to send at all are the rulelib/order-email.js, which the other
app now asks as well. The key is opened where it is used and never held.A shop on its own mail server is still sent to the other app, and that is
written down rather than discovered:customis SMTP — a socket, EHLO,
STARTTLS, a dialogue — and a second implementation of a protocol is how two
apps come to disagree about whether a customer was told. The refusal names
it now ("an email through your own mail server (SMTP)") instead of saying
email is missing, because those are different things to a shop deciding what
to change.
Fixed
-
No email has left Khayt since 31 August, and nothing said so. Three
functions — the status notification to a customer, Email on an order or
quote, and the printer-alert digest — each open with
const shopName = shopName() || 'Khayt';.shopNameis also a global
function, so theconstshadows it and the line reads the binding before it
exists:ReferenceError, thrown before anything is addressed, every time
since it appeared in #822. Nobody awaited those calls, so each became an
unhandled rejection — no toast, no error, no email. A shop that finished a
job watched it move and had no reason to think the customer had not been
told. The local is renamed in all three; a test now fails on anyconstor
letinrenderer/that shadows the function it calls. -
An unconfigured mail provider built and addressed an email nobody could
send. WithemailConfig.providerset to the empty string — never
configured, or cleared — the renderer refused only the literal'none', so
it assembled the whole message and handed it to a transport that matches no
provider, which returned amailto:fallback the caller ignores. Meanwhile
outboundFor, which decides whether a move reaches outside the shop, said
the opposite. Both halves now ask one rule, and the answer is the true one:
nothing is delivered, so nothing is built.
Khayt for macOS 4.0.0-alpha.8
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Changed
-
Take a job from something you already make. A product in the catalogue now
has New Job from This: its parts, its components, its margin and its name,
filled in — and then it is an ordinary job sheet, because a customer who wants
two in a different colour is still ordering the product.The job names the product, which is what the catalogue counts to say a
thing has been made 14 times and earned 6,300. A job typed out by hand that
happens to match is not counted, and nothing on that screen says so.Its components come with it — the magnets, the screws, the box. A job
without them is under-priced by exactly their cost, every time it is sold. -
Pricing tiers can be added on the Mac, and picked where they are used.
A product can carry named margins — Retail 45%, Wholesale 20% — and they are
offered as chips beside the margin on the job sheet. A margin and not a price,
so a tier stays right when filament gets dearer. -
Documents can be attached to a product here. Assembly instructions, a
safety sheet, a drawing. A copy is taken, so your own file can be moved or
renamed afterwards. Each one says whether it goes in the customer's box or
stays on the floor's copy — and they are listed on the job, which is where
somebody stands when they are about to make the thing. -
Ask what to charge, beside the figure you already have. The job sheet
already shows what you usually make on work like this. Ask what to charge
now sends those comparables — and only those — to be weighed, so an outlier
or a thin sample can be argued about in a sentence rather than averaged away.The reason is always shown. A margin that changed with no sentence beside
it is a number you cannot argue with when a customer does.If the answer is unusable, your own median is what comes back — it was worked
out on your Mac before anything was sent, so a refusal is not a failure. -
Finishing a job on the Mac now tells the systems you have connected. A
shop with webhooks configured could not move a job on the Mac at all: the app
refused the move rather than make it with a piece missing. It sends them now,
so that refusal is gone — and both webhook systems are covered, the
subscription list and the single order webhook, because a shop can have both
and Khayt sends to both.The message goes out after the job is saved and only if it was, and a
delivery that fails is said out loud rather than swallowed — the whole point
of refusing these moves before was that a piece of the move would silently not
happen. -
(Maintainers) The webhook payload and its envelope are shared rules now.
Two apps sign the same bytes, so the field names, their ORDER, and the
{ event, payload, timestamp }envelopemain.jshas posted since webhooks
shipped are all inlib/webhook-bus.jsand used from both sides. A literal in
one app would have meant deliveries that verify from Khayt and fail from the
Mac, which is the kind of drift a shop only discovers through a consumer that
stopped trusting it.The signature is the bare hex, not
sha256=<hex>.main.jshas two webhook
transports that disagree about this, and the bare one is what every delivery
actually goes through — so it is the spelling consumers verify. -
(Maintainers) The Mac can send a webhook, with both layers of the guard.
The transport, the HMAC signature and the retry policy.The URL is typed by the shop, so the guard is the feature. Two layers, and
neither is enough alone: the name is checked against the shared ranges —
loopback, RFC1918, link-local, cloud metadata, and the spellings that hide
them ([::1],::ffff:127.0.0.1in both forms,2130706433) — and then the
host is resolved and every answer is put through the same rule, because a
perfectly public name can have an A record pointing at10.0.0.1. Redirects
are not followed: a consumer answering302to a metadata endpoint would walk
straight past both. -
(Maintainers) The host ranges are a shared module now. They were the top
oflib/host-guard.js, which cannot be shared — it requires Node'sdnsfor
its second layer.lib/host-ranges.jsholds the pure range checks and
host-guardre-exports them, so there is exactly one copy of rules that are
almost entirely made of holes somebody already found. Its 19 existing tests
pass unchanged through the re-export. -
The Mac can draft a message to a customer. On a job with a customer on it:
pick what the message is about — a status update, ready for pickup, a quote
follow-up, a payment reminder, an apology for a delay, or your own note — and
it writes one.It drafts. It does not send. The message comes back in a box you can edit,
with Copy under it, and you send it through whatever you actually use. A
message written about somebody's order, in your shop's name, is not something
to put on the wire before a person has read it.This is the one feature that sends another person's data, and what travels is
exactly what the settings screen says: the customer's name, the order
reference, project, status and due date, and the amount and outstanding
balance. Their email address, phone number and address are on the same record
and are not passed — which is a test, because handing the whole record
over is the obvious way to write this and the disclosure would quietly stop
being true. -
You can ask the Mac about your own book. "How did this month compare with
last?", "How much is still owed to me?" — in the Book menu, when you have
switched the assistant on.It is given a summary, not your book, and the screen says so before you
ask anything: totals, counts and what is outstanding. No customer name, email,
phone number, order reference or project title is in what leaves your Mac —
and that is a test, not a promise, because it is exactly the sentence that
would quietly stop being true when the summary gains a field.The suggested questions are the ones the summary can actually answer. A blank
box with a cursor in it is a test a shop can fail. -
A product made from an unsliced model now has a weight, a time and a
price. Most of a shop's library is models nothing has sliced yet, and those
files record no weight and no time — so the product arrived with neither,
which meant no cost and therefore no price at all.Khayt measures the mesh and prices it at the rate your own finished jobs
actually ran at. Where the file cannot answer, the geometry does.It says the figures are estimates, and says it two different ways: one
sentence when the rate came from your own measured jobs and names how many,
another when there are none yet and it is an assumption. An estimate that
looks typed is the same mistake as a zero that looks typed. -
Comparable margins are net of tax — which changes a figure Khayt has been
showing. AI price assist recommends a margin from what a shop has actually
realized, and it computed those margins against the gross price. For an
inclusive-VAT shop — Saudi, the Gulf, most of Europe — part of every price was
the tax authority's and was never revenue, so every comparable overstated.A Riyadh shop at 15% was shown a median of 56.5% where it had made 50.0%,
and pricing to the number it was shown leaves it thinner than it thinks by
exactly that much. An unregistered shop's figures do not move: its price is
its revenue.(This shipped in the previous release under a product-pricing change, which
did not describe it. It moves a number a shop may have priced against, so it
is written down here.) -
The Mac shows what you usually make, before you pick a margin. On the new
job sheet: "You usually make 34% on PETG — median of 6 finished jobs.",
with one click to use it.No AI is involved and none is needed. It is arithmetic over your own
finished jobs, so it works with the assistant switched off, with no key, and
with nothing sent anywhere. Net of tax, for the reason above. -
(Maintainers) What still needs the other app is a test, not a claim.
NeedsTheOtherAppTestsholds the list, and it is closed: a screen that sends
a shop to Khayt without a declared entry fails the suite, an entry for
something already working fails it too, and the count is a ratchet. Three
times this session a screen was found telling a shop to go elsewhere for
something the Mac had done for weeks — each true when written. -
A product made from a model recorded its quantity in a field nothing
reads. Make a product from this wrotequantitywhere every consumer
readsqty— the calculator's per-part cost, the packaging split, the price
tiers, and the specs a catalogue row shows. So the real field was absent and a
junk one sat beside it.Benign only by accident: the arithmetic falls back to one where
qtyis
missing, and the value written was always one. It would have stopped being
benign the moment anything wrote a different number. Found in a real shop's
book. The test that covered this path assertedquantity— it agreed with the
code rather than with the rule, which is why nothing caught it. -
A product added on the Mac now has a price. It did not. The sheet could
not hold the product's parts, and a product's price is made entirely of
them — so one written down here saved at 0.00 with no hours and no grams, and
had to be finished in the other app before it could be sold.Parts are on the sheet now: name, spool, grams, hours, quantity. The cost, the
price and the totals appear as you build it, so a margin typed above is no
longer a number chosen blind. A part with no spool chosen says that it costs
nothing and that savin...
Khayt for macOS 4.0.0-alpha.7
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Added
-
The assistant has a screen of its own. Khayt's AI features could be
switched on in the other app and not this one, so a shop on a Mac could be
told a feature was running and have no way to see — let alone refuse — what
it sends. Settings → AI assist now carries both halves together: which
provider you use, and a switch per feature with what each one transmits
written beside it.The two halves ship together deliberately. A provider chooser on its own
would let you point Khayt at a vendor without being told that drafting a
customer reply sends their name, their order reference and their outstanding
balance. A list of switches on its own would name a vendor you had not
chosen. The one that sends a customer's data is badged as such, and nothing
on the screen works consent out for itself — it asks the same rule the gate
asks, so a feature can never read as off while it runs.Your key is sealed with the book's own key before it is written, the same way
a printer's key is, because this file syncs, is backed up and is exported. A
key that cannot be sealed is refused rather than stored in the clear. -
A model in your library can become a product. The library knew what
each model weighs and how long it takes — parsed when you imported it — and
the catalogue asked you to type both in again. Make a product from this is
on the Model menu and on a model's right-click menu, and the product arrives
with its first part already filled: weight and time from what the slicer
measured, material and layer height from the setup you have had most success
with.It is joined to the model, not just named after it. A part used to carry
the file's NAME — a filename somebody typed — so nothing else could follow
it. It carries the model's identity now, which is what makes "for this part,
at these settings, how far out is my estimate?" answerable later.What the file cannot answer for is named on screen rather than left at zero,
because a zero that looks typed is worse than a blank you were told about. -
Khayt can show a camera that only speaks RTSP — which includes the Buddy3D
that sits beside a Prusa CORE One. Give the machine the camera's address as
rtsp://…and set its type to RTSP; Khayt opens the stream, takes one frame,
and hangs up, the same way it takes a still from any other camera. The
camera has to be publishing locally first: switch on "RTSP stream on local
network" in the Prusa app, or the camera answers "no stream" and the tile says
it is waiting. Mac only for now — the Windows and Linux app has no decoder. -
A printer that changed address can be found again. A DHCP lease
expires overnight, the router hands out a different address, and Khayt polls
a host that answers nothing. It said offline — which is also what it says
when a printer is switched off, and the two have completely different fixes.A machine that has gone quiet now offers Find it on the network. Where the
printer announces the serial or the hardware address Khayt recorded — neither
of which moves with a lease — that is identity, and one click points Khayt at
it. Where the evidence is only that exactly one printer of the right model is
answering, it says so and asks you to check first, because pointing the app
at a machine is what it will later send commands through.What this was costing. Khayt freezes a job's real filament and duration
on the edge out of printing, because the printer's counters reset when the
next job starts. Every print that finished while the address was stale is a
measurement that no longer exists — found exactly that way when a Snapmaker
U1 moved from .77 to .56 and the completion history came back empty rather
than short. -
What a model would take, before anybody slices it. Khayt could
measure a mesh from the day it could read one and could never price one — a
model you had not printed showed a size and a triangle count and no answer to
the question you actually had. The library inspector now says what it would
take in filament and in hours.It does not ask how fast your printers are, because nobody knows that about
their own printer. The estimator's hardest number had been the same guess
for everyone since it was written. It turns out not to need guessing: it only
ever appears multiplied by density, and that product is grams per hour —
which every job whose real weight and duration were recorded has measured.
So Khayt learns it from your own work, says how many jobs it learned from,
and says plainly when it is still using its own default instead.It will not learn from a job nobody measured, from one job, or from a figure
divided across several parts — calibrating an estimator against its own
estimates teaches it nothing.Settings → Preferences carries the four numbers you can answer for: density,
infill, wall thickness and waste. There is deliberately no field for the
speed. -
The Mac app can group several prints that are one object. A figure
printed as a head, two hands and a body on four evenings is four jobs in the
book, and "what did that figure cost me" was arithmetic across four rows that
nobody does. The Electron app has grouped them since its Orders Log learnt to;
the Mac could not. A kit now sits above the jobs table with its own totals,
clicking one narrows the book to the jobs that made it, and the selected job
says which kit it belongs to and what the whole object came to.Grouped ACROSS orders rather than merged into one, and that is not tidiness:
what a print really took is recorded on the ORDER and nowhere else, so folding
four jobs into one would replace four measured numbers with one — and those
four are exactly what the estimator learns its rate from.Every total says how many jobs are behind it. Adding up what four prints
took, when one of them was never measured, gives a figure that looks like the
answer and is the answer for three. So a kit that is not fully measured says
"3 of 4 measured" in amber, and offers no percentage against the estimate at
all — an estimate covering four jobs and an actual covering three do not
divide into anything true.Naming is a pick rather than a retype: a name a kit already has IS that kit,
whatever the capitals, and a name one edit away from an existing one is
questioned before it becomes a second kit with the takings split between them.
A kit whose name was deleted keeps its jobs and can be named again. -
A product can have more than one picture on the Mac, and each says what it
is. The catalogue held one: a shop selling a printed part chose between a
render, a photo of the real thing, a scale shot and a detail of the finish.
The product sheet now carries a strip — add several at once, drag the order
that matters, and label each one.The label is the point rather than the count. A customer looking at a listing
is asking a question the pictures rarely answer — is that a render, or is
that what arrives? — and guessing wrong is a refund. The first picture is the
one the catalogue, the storefront and the invoice use, which the sheet now
says in words instead of leaving it to be inferred from a row of thumbnails.Nothing touches the pictures folder until Save. A picture picked and then
cancelled leaves no file behind, and one removed and then cancelled is still
there. -
The Mac can connect a storefront. Khayt's cloud serves an import route per
platform — paste it into Salla, Zid, Shopify or WooCommerce as an order
webhook and new orders arrive in Order requests — and a feed route that
publishes the catalogue back. Both links were built and shown only by the
Electron settings page, so a shop keeping its book on the Mac had the cloud,
had the shop id, and no way to find out what to paste. There is an
Integrations pane now, with the storefronts and payment systems for its
market, and a market picker for a shop that sells into more than one.Medusa gets the code as well as the link. It is a self-hosted framework with
no webhook settings to paste a URL into, so Khayt hands over the subscriber
file to save in the shop's own project — the link on its own would be a URL
with nowhere to put it.Switching a payment system on in one market cannot switch another market's
off. The directory shows one market at a time, and a shop selling into two has
providers configured outside the list on screen; the save merges rather than
replaces, so the first the shop would have heard of it is an invoice that
stopped offering a way to pay.
Changed
-
The Mac app wears the new icon's colours. Khayt's accent was the cyan of
the icon before last, and the app had been sitting beside its own orange-on-
navy mark looking like a different product. It is now the mark's navy, at the
lightness a label can actually be read at — 5.60:1 on the lightest surface it
draws in light appearance, 5.26:1 in dark, measured against the real card and
ground colours rather than against white.The accent is the navy and not the orange, and that is the finding. The
obvious move on a re-brand is to take the mark's loudest colour. Measured, the
filament in the new icon is hue 23° and Khayt's "something is being made right
now" was already hue 19° — four degrees. The new icon did not bring an orange
to the app; it agreed with the one already in it. Spending that hue on
selection, links and section rails would have cost the app the one colour that
means printing, on a dashboard that draws exactly that distinction on a
single control. So the accent is the mark's other colour, and both halves of
the icon are now on every screen.The informational colour moved with i...
Khayt for macOS 4.0.0-alpha.6
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Fixed
-
Khayt no longer quits when you Quick Look a second model. Going through
the library pressing ⌘Y, the app disappeared on the second one — with no
error, no crash report and nothing to look at afterwards.The preview panel's binding was never cleared when a panel was dismissed, so
the second look handed it one file where another already sat. Every look is a
fresh one now, and both ways in — ⌘Y and the model's own menu — go through
the same door, which is what stopped one of them being fixed and the other
not.
Khayt for macOS 4.0.0-alpha.5
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Changed
-
Khayt has a new icon. A chrome nozzle extruding a single thick loop of
orange filament in the shape of a khaa, on deep navy — one mark at every size,
from the 1024px Dock icon down to the 16px favicon, instead of a detailed
drawing that dissolved into a smudge when it got small. The mark is drawn once
and all 72 shipped assets are derived from it, so the 32px and the 512px can
no longer disagree.Three things this fixes on the way through. The marketing site's two favicons
were declared 16 and 32 and were both actually 64. Its apple-touch-icon was
256 with transparency, which iOS composites onto black. And the AppX badge was
a colour downscale where Windows wants a monochrome glyph it can tint per
theme. -
(Maintainers) The Mac app has a macOS 26 layered icon. It shipped a flat
legacy.icns, so it got none of Tahoe's Liquid Glass, dark or tinted icon
treatment. Background and foreground are separate layers now.The UI accent has deliberately not moved with it. Every contrast ratio in
mac/README.mdwas measured against the old cyan, so re-accenting is a
measured pass rather than a substitution.
Added
-
Khayt can tell you what is likely to go wrong before you quote.
Select a model and the inspector says what a slicer would find: how much of
the surface overhangs past 45° and will need supports, how much is
near-horizontal underside that sags rather than merely printing rough, and
whether the walls average thinner than the nozzle can lay down.Every line carries the measurement it is based on, so you can disagree with
it. A shop that supports everything by default can see at a glance which
line to scroll past, and a part with nothing wrong says so — "nothing to
flag on this one" is a different answer from not having looked.It works on the files you actually own. The other Khayt computes the same
findings for a quote, but it has to build the whole triangle list to do it
and gives up past four million facets. Two models in this library are past
that. The Mac reads the mesh as a stream and keeps ninety-one numbers, so the
size of the file stops being the question.Under Settings → Preferences you can choose when Khayt looks: when you
ask, which is the default, or as each file is imported. Reading a mesh
is a few seconds on a large model — paying that during an import answers
instantly forever after, and leaving it until you ask keeps imports fast.
Either way the answer is kept, so the same model is never read twice, and it
is thrown away if the file behind it is replaced. -
Adding a spool can be a lookup instead of typing. Start typing a
brand or a product — "bambu matte", "esun petg" — and Khayt offers the
filament and its colours from a bundled catalogue of 1,945 products, filling
in the name, the colour, its hex and the spool weight.It fills in what a manufacturer can know and nothing else. Your cost, what the
roll weighs today, when you opened it and whether you have dried it are facts
about the spool in your hand, and nothing here invents them — and editing a
half-used roll never overwrites what is on it.The list ships with the app, so it works with no connection and Khayt does not
tell anybody what you buy. It says how old it is rather than pretending to be
current. From the Open Filament Database, MIT-licensed — see
THIRD-PARTY-NOTICES.md. -
A job's parts can be corrected. They were read-only: a weight typed
wrong when the job was taken stayed wrong, and the only way to fix it was to
open the job in the other Khayt. Double-click a part to change its name,
filament, weight, hours or quantity.The price is not a field you type. A part that weighs 40 g rather than
30 g costs more to make, so the figures you know are asked for and the price
follows from the same cost model the calculator uses. Correcting a weight
corrects the job.Where the part came from a model in your library, Fill from file takes the
weight and time the slicer measured. It shows you both figures first rather
than overwriting quietly — a part may have been corrected on purpose — and it
says which fields the file could not answer for instead of leaving zeros that
look typed. -
A print made of several files says so. A head, two arms and a torso
are one thing you print, not four — but the Mac app showed a kit as a single
entry with the rest of its files invisible. The model's panel now lists every
file in the print, marks the one the card speaks for, and adds up what the
whole thing weighs on disk.Where a file could not be measured it says so, and the total is left off
rather than quietly adding up the parts it could measure and presenting that
as the size of the print. -
An invoice says whether it has actually been reported to ZATCA.
Khayt already put the Phase 1 QR on the document. What the Mac app could not
tell you was whether an invoice you had handed a customer had been reported to
the tax authority at all — which is the part a Saudi shop can be penalised
for, and it was invisible on this side. A completed invoice now says
submitted, not submitted, rejected or errored, with the counter value and, if
it was refused, the reason it was refused.It does not offer to submit. Signing the document needs code that only runs in
the Electron app, and a button here that could not finish the job would be
worse than a plain statement. Nothing appears at all on a shop that has not
switched Phase 2 on, because none of this applies to it. -
Khayt remembers what a print actually worked at. A file counted how
many times it printed and how many times it failed, but not with what — so
reprinting a bracket six months later you knew it had worked once and had no
idea on which printer, in which material, at which layer height. The model's
panel now lists the settings it has been printed at, marks the one to reach
for, and says plainly when nothing has worked yet rather than naming the least
broken option.One bad print does not condemn a setup: filament runs out, a spool tangles,
somebody knocks the machine. Nine of ten is still a setup to reach for, and
one of four is not, however recently that one worked. A setup nobody has run
reads as untried rather than as a score of nought — and your own verdict
overrides the tally, because "it printed, but I did not like the finish" is a
judgement no counter can reach. -
A print that exists at more than one size says so. Big and small
carry their own weight and time, so the panel shows each with its own figures
and marks the one the estimate is about. Files that have only ever been one
thing — nearly all of them — are unchanged. -
Khayt says what is about to run out that is not filament. Glue, IPA,
mailing bags, spare nozzles — running out of one of those stops a job exactly
the way running out of filament does, and only filament reached the Mac app's
shelf. The inventory screen now leads with what needs ordering, in each item's
own unit.Three different reasons put something on that list and they read differently:
it has run out, it is below the minimum you set, or nothing is wrong yet and
the rate you are getting through it says otherwise. The last is the one you
cannot see by looking at the rack. Where Khayt has no usage figure and you
have set no minimum, it says the item is low and stops there rather than
inventing a quantity to put on a supplier's order. -
Khayt tells you what each printer is due for. A machine card now
lists the recurring jobs set against that printer — replace the nozzle, clean
the plate, check the belts — with how far off each one is and a button to mark
it done. Amber when it is close, red when it is past, and nothing at all on a
printer nobody has set tasks up for.The hours are the hours Khayt has logged, counting finished prints only. A
cancelled print used some of the machine's life in reality, but the log has no
honest figure for how many, and counting the whole estimate would bring
services forward on exactly the printers that fail most. -
Khayt finds printers on your network. Adding a machine meant knowing
its address and typing it — and a shop that has just plugged a printer in does
not know it, so the number gets copied by hand off the printer's own screen
across the room. Find printers on the machines screen asks the network
instead, and adding one fills in its address, its connection type and — when
Khayt recognises the model — its bed, nozzle and running cost.The scan is owner-initiated and time-boxed, never on a timer, and macOS asks
your permission the first time. A printer Khayt can see but cannot yet speak
to says so rather than being added as though it were ready. -
(Maintainers) The mDNS codec runs on the Mac now.
lib/mdns.jswas built
on Node'sBuffer, which JavaScriptCore does not have — so the one piece of
wire-format code both apps need could be loaded by only one of them, and
finding a printer on the Mac would have meant a second implementation of DNS
name compression. Two codecs is two chances to mis-read a packet arriving
unauthenticated from the workshop network. It isUint8Arraythroughout now;
Bufferis aUint8Array, so nothing in the Windows and Linux app changed. -
Khayt can tell a printer what to do. The Mac app could watch seven
protocols and touch none of them: it knew a print was failing, it knew which
machine, and stopping it meant walking to the printer or opening the other
app. Pause, resume and cancel are on the machine card now, while something is
running. Cancelling asks first — it throws away every hour already in the
pl...
Khayt for macOS 4.0.0-alpha.4
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Added
-
Khayt says what to run next. It knew the queue and it knew which printers
were idle; putting the two together was a person doing it in their head. The
machines screen now proposes a job for each free printer — urgent first, then
due date, then longest waiting, and preferring the machine already loaded with
the right material so there is one fewer spool change.It proposes; you press Send. No printer Khayt talks to can clear its own
plate, so an idle printer is very often an idle printer with yesterday's part
still on it. A machine is only offered once somebody has said its bed is clear
since its last print — and a machine waiting on that says so, with the button
to say it, rather than quietly disappearing from the list. -
Help, in your own language. Sixteen articles — the book, jobs, the board,
customers, the library, the catalogue, the shelf, machines, money, reports,
cloud sync, backups, settings, the keyboard, and what to do when something is
wrong — in English and Arabic, searchable, from the Help menu or ⌘?. It opens
in a window of its own so you can read it beside the screen you are asking
about, and it follows the language Khayt is set to rather than the Mac. -
A product can be written down here. The catalogue could be read on this
Mac and not added to. There is an editor now, with one tab per language your
catalogue carries rather than a fixed English and Arabic. Everything the sheet
does not show is left exactly as it was: parts, prices per quantity, photos
and documents. -
The catalogue can be looked at, not only read. A grid of photographs
beside the existing table, which stays the default because it is the only view
that puts margin next to weight. -
Importing models is on the library, and keeps your folders. An Import
models button, and you can drag files or whole folders straight onto the
library. The folder a model came from becomes the group it is filed under —
a download of seven models in seven folders arrives as seven groups. Packaging
folders are seen through: a model atKings/King Abdulaziz/STL/presupported/
is filed under King Abdulaziz.
Fixed
-
A printer was credited with colours it does not have. Adding a Prusa CORE
One gave Khayt a machine it believed could print five colours. Five is what a
CORE One reaches with an MMU3 bolted on; the one on your bench prints one. The
same was true of every Bambu without an AMS, every MK4 without an MMU, a K2
Plus without its CFS and a Kobra 3 without an ACE — and capacity, colour
warnings and the converter all believed it.A machine is now added with the colours it prints as sold. Machines whose
multi-material is built in — a Snapmaker U1's toolchanger, a J1's IDEX, the
dual-extruder UltiMakers — are unchanged. -
Four screens had a search box that did nothing. The calculator, the colour
studio, the reports and the dashboard are not lists, and the field on them
could be typed into to no effect — while saying "Job, customer or number". It
is gone from those. The catalogue, which is a list, now searches by name,
description, material and group.
Khayt for macOS 4.0.0-alpha.3
Khayt for macOS only. The Windows and Linux app is unaffected and is on its own
version — see VERSIONING.md.
Before you update
If you have 4.0.0-alpha.1 or 4.0.0-alpha.2, download this one by hand.
Those builds cannot launch, which means they cannot check for updates either —
Sparkle runs inside the app, and the app stopped before it started. Nothing will
arrive on its own. Drag the new Khayt into Applications over the old one.
Fixed
-
The Mac app could not launch on any Mac that had not built it. Both
published alphas were signed, notarised, stapled — and dead on their first
line:Fatal error: could not load resource bundle: from /Applications/Khayt.app/KhaytCore_KhaytCore.bundle or /Users/runner/work/Khayt/Khayt/mac/KhaytCore/.build/…Khayt's business rules are JavaScript the app loads from inside its own
bundle, and it asked SwiftPM'sBundle.modulewhere that was. That is not a
search: it compiles down to two fixed paths — the app bundle's root, where
nothing may be put because codesign seals only what is insideContents/,
and the absolute path of the build directory on the machine that compiled
the app. On a developer's Mac that directory is right there, so every build
made here ran perfectly, by reaching outside the app into it. On the release
runner that path is/Users/runner/work/…, which exists on no shop's Mac.The app finds its own resources now, in
Contents/Resources, where they have
always been. -
An invoice would have printed with no styling at all, and the sample book
would not have opened — the same cause, one layer quieter. Neither crashes,
so neither would have been reported as this: a shop would simply have sent a
customer a document that looked like raw HTML.
Added
- (Maintainers)
Khayt --check-resources, and the release runs it. The
reason this shipped twice is that nothing in the release ever asked the built
app a question. Launching it would not have helped — CI is a build machine
too, so a broken app starts there. The app is asked where it found each of
its resources, and the answer has to be inside itself.Bundle.moduleis
banned in this package's own sources, with a test that says so.
Khayt for macOS 4.0.0-alpha.18
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Added
- (Mac) A listing can be taken off the catalogue. There was no way to
delete a product here at all — the words for it had been sitting in the app
unused. Right-click a product in the grid or the table and it asks, in
Khayt's own sentence, which names what survives as well as what goes: the
photo is removed, past invoices are kept. Deleting also unlinks every job
that named the product and drops it from any quote bundle, because a job
pointing at a product that is not there is the kind of fault that surfaces
months later as a screen that cannot draw. All of it comes back with one
undo, except the pictures, whose bytes are gone — the record is restored
without them rather than naming files that no longer exist. - (Mac) Settings → Online can switch public pricing on, and make the
printer preset it needs. The customer-facing price is built from a saved
preset — a name and the seven figures a part is costed at — and the shared
rule refuses outright without one. Until now a preset could only be made in
the other app's calculator, so the Mac could serve the upload and never
answer. The pane now carries the whole block (the switch, the preset, the
material or a flat spool cost, margin, minimum, waste and the per-visitor
hourly ceiling), says plainly when there is no preset yet, and will make
one: name it, adjust the seven figures, and it is saved and chosen. A name
already in use replaces that preset rather than doubling it, which is the
other app's rule and the same id, so anything pointing at it still does. - (Mac) A customer can price their own model on the intake form. With
public pricing switched on, the form offers an upload: the file is measured
in memory, priced on the shop's own preset, spool cost, margin and waste
allowance, and the figure is shown as an indication rather than a quote. A
sliced file is taken at the slicer's own weight and time; an STL, OBJ or
3MF is measured by this app's own reader. Nothing is written to disk — the
model is read and dropped, so there is no stranger's file on the shop's
machine to keep or explain. When the request is submitted, the price
attached to it is the one THIS server produced, recalled by reference, so
a browser cannot post a figure of its own. The rules are the shared ones
(lib/public-quote.js,lib/gcode-parse.js), which the other app already
quotes through, so a customer is never shown a different sum from the one
the shop would reach for the same part.
Fixed
- A delivered job was missing from what its printer had earned, in both
apps. Khayt wrotedeliveredbefore it wrotecompletedwith a
deliveredAtbeside it, and both are still in shops' books — thirteen of
them in the sample. So "is this job finished" is a two-value test, written
out by hand in eight modules and got wrong in three places: the machine
P&L in both apps, and the machine revenue chart. Each filteredcompleted
alone, so a shop that marks work delivered saw its printers' earnings
computed on a subset, with nothing to say so.lib/order-status.js—
which already says in its own header that it exists so the two apps cannot
disagree about whether a job is finished — now names the test once, and
the three callers ask it. A test holds the Mac's copy of the list to the
rule's own, and another checks the charts have not gone back to comparing
by hand. - A multi-colour print weighed nothing, so anything made from it cost
nothing. A one-material slice reports a single filament weight, and that
is the only figure this read. A toolchanger does not produce one: a U1, an
XL or an AMS slice writes a weight per filament, which the library keeps
per colour. So every multi-colour file reported "no weight", and a product
or job made from one came out costing nothing — a 57 g dragon read as zero.
On the shop's own library, three of 152 files carried a weight and all
three carried it this way, so the branch that was read had never once
matched. The colours are summed now, and labelled as the slicer's own
arithmetic rather than an estimate, because that is what it is. A file that
genuinely knows no weight still says so. - Public pricing settings were dropped on the way to the book. The shared
settings save merges the LAN block by naming the fields it knows, and the
model-pricing block was not among them — so a pane that set a margin and a
preset would have had both discarded on save, silently. It is merged whole
now, over what was stored, so a field a newer build wrote survives a save
by an older pane. - (Mac) A resin printer's progress was captioned with a claim about a file
it does not have. The machine card names which signal a percentage came
from, so that "by layer" and "by file position" can be told apart on a
Moonraker printer. It was meant to say that only for Moonraker, which is
the one adapter that chooses between two signals — butlib/sdcp.jssets
the same field, totimeornone, and anything the card did not
recognise was captioned "by file position". So an Elegoo resin printer
reporting its own elapsed ticks was described in terms of a file it never
had. The adapter now decides whether to caption at all, and a signal this
app has not been taught is left undescribed rather than described wrongly. - (Mac) A product made on the Mac was priced on its filament alone. The
other app's calculator puts a labour rate, prep and post time, power draw,
electricity, wear and a failure allowance on every part it writes; this
sheet wrote none of them, and the shared pricing rule injects none on
purpose. So a product added here cost whatever its filament cost and
nothing else — on a real portrait, 10.57 where the true cost is 35.91,
because those seven figures are seven tenths of what it takes to make.
The part being added now carries the same starting figures the other app's
form carries, folded away under "Labour, power and wear" so they can be
changed before the part goes in, and a part already in the list that has
none of them says so instead of quietly costing less.
Khayt for macOS 4.0.0-alpha.17
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Added
- (Mac) The shop's due dates as a calendar subscription. With the LAN
server on, Settings → Online shows the same/calendar.icslink the
Windows and Linux app offers: one all-day event per open job with a due
date, tentative until it is printing, for any calendar app on the shop's
Wi‑Fi. The feed is one shared module now (lib/lan-calendar.js), lifted
verbatim out of the Node route and held byte-identical to it; the
subscription token is minted into the book the first time the Mac serves. - (Mac) "Where is my order": the customer's tracking page, served by the
Mac. On a job under way or done, the inspector has "Copy tracking link":
the link points at this Mac, carries the job's own tracking token (minted
the first time, as the other app mints it) and opens the same page that
app serves — the stage of the order, its details, the shipping, and once it
is complete a short survey the customer can answer from the page. The page
is lifted verbatim out of the Node route intolib/lan-order-page.js, the
Node server draws from it, and the carriers directory moved from the
renderer intolib/so both hosts read the same carrier names and links.
Fixed
- Time left on a Klipper printer is the figure the machine itself shows.
Khayt worked the number out from the layer count, and a layer count assumes
every layer costs the same. Measured on a U1 printing a part whose lower
half held three quarters of the work: layers said 53% done and Khayt
extrapolated 7h19m left, while the machine's own screen said under three
hours. Both numbers were in front of the shop at once. Klipper relays the
slicer'sM73percentage — the only one of the three signals that is about
time rather than geometry or file layout — asdisplay_status.progress,
and Khayt was not asking Moonraker for it at all. It asks now, and prefers
it, captioned "as the printer shows it" so the two can be checked against
each other. Layers stay the fallback: a file with noM73behaves exactly
as before, including the relief whose byte position read 0.7% at 19% done.
Khayt for macOS 4.0.0-alpha.16
Khayt for macOS only. The Windows and Linux app is on its own version — see
VERSIONING.md.
Added
- (Mac) The phone's live queue, served by the Mac. A new Online tab in
Settings carries the LAN block the Windows and Linux app keeps under
"Advanced": enable the server, listen on the shop's Wi‑Fi, set the owner
PIN. Switch it on and a phone on the same network gets the same live queue
page, status API, queue API and installable home-screen icon that app
serves — the same bytes, from one shared module (lib/lan-pages.js), behind
the same PIN and the same lockout rules (lib/lan-auth.js), with the same
security headers on every response. Saving restarts the server when the
port or the PIN changed. The intake form, quote approval, the calendar feed
and the webhooks are still the other app's; they follow. - (Mac) The customer intake form, served by the Mac. With the LAN server
on,/intakeon a phone or laptop on the shop's Wi‑Fi is the same request
form the Windows and Linux app serves — same page, same session cookie,
same limits on opening and submitting it, same consent record — and a
submitted request lands on the Waiting screen at once. The form's template
and the rule that turns a submission into a waiting-list entry are one
shared module now (lib/lan-intake.js); the Node server draws from it and
is held byte-identical to its old handlers. Not yet on the Mac: pricing an
uploaded model on the form (the form does not offer the upload here) and
the legacy intake PIN route. - (Mac) A customer approves a quote from their phone. On a job that is a
quote, the inspector has "Copy quote link": the link points at this Mac,
carries the job's own approval token (minted into the job the first time,
as the Windows and Linux app mints it), and opens the same quote page that
app serves — the parts, the total in the shop's currency, the expiry, and
one button. Approving moves the job to pending inside the write on the
newest book; a quote that expired, or was already approved, gets the same
answer the other app gives. The page's small companions (not found, bad
link, expired, cannot approve, approved) are lifted out of the Node routes
intolib/lan-quote-page.js, verbatim, and the Node server draws from
them; the rule's clock is injectable so both hosts can be held to it. Not
yet on the Mac: the order tracking page and the legacy POST /order/:id. - (Mac) Rounding and "Your own price" on the product sheet. The two
controls Khayt's product editor has had all along — round to a step (up,
down or nearest) and a typed price that wins over everything — with the
price preview following them as they change. Until now a shop on the Mac
could see a catalogue price move and had no way to set it back. - The shared settings save (
lib/settings-edit.js) now takes the LAN block
from a form and merges it the way the Electron page always did: the fields
shown over the stored block, a blank PIN keeps the current one, a port that
is not a port is 3219. The Electron page is unchanged.
Fixed
- (Mac) Saving a product no longer throws away its cost inputs or its
price. The Mac product sheet rebuilt every part from the five fields it
shows, so the labour rate, prep and post time, power draw, wear and failure
rate the other app had priced the part with were dropped on save — a
portrait that cost 35.91 to make came back costing 10.57, and the product
re-priced itself from 50 to 13.74. The save also ignored the product's own
rounding and typed price. Now a part keeps every field the sheet does not
edit, and the product is priced through the shared rule with its rounding
and override, so the same product saves to the same price in both apps. - (Mac) "New job from this" prices the job at the product's own rates.
The job's parts were costed from grams and hours alone, so the same
portrait opened at 15 where the catalogue said 50. A part taken from a
product now carries the product's rates into the cost, and the job opens at
the catalogue price.